├── .dockerignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── deploy.yml │ ├── rubocop.yml │ └── ruby.yml ├── .gitignore ├── .gitpod.yml ├── .rubocop.yml ├── .rubocop_todo.yml ├── .ruby-version ├── .yardopts ├── CHANGELOG.md ├── Dockerfile ├── Dockerfile-dev ├── Gemfile ├── Gemfile.lock ├── LICENSE.md ├── Procfile ├── README.md ├── Rakefile ├── VERSION ├── app ├── assets │ ├── images │ │ ├── b_browse.png │ │ ├── b_drop.png │ │ ├── b_edit.png │ │ ├── b_user.png │ │ ├── b_users.png │ │ ├── dots-white.gif │ │ ├── error.png │ │ ├── euro.png │ │ ├── euro_new.png │ │ ├── icon_message.gif │ │ ├── lamp_grey.png │ │ ├── lamp_red.png │ │ ├── loader.gif │ │ ├── package-bg.png │ │ ├── package.png │ │ ├── rails.png │ │ ├── redbox_spinner.gif │ │ ├── role-admin.png │ │ ├── role-article_meta.png │ │ ├── role-finance.png │ │ ├── role-invoices.png │ │ ├── role-orders.png │ │ ├── role-pickups.png │ │ ├── role-suppliers.png │ │ ├── save_pdf.png │ │ └── text_file.png │ ├── javascripts │ │ ├── application_legacy.js │ │ ├── article-form.js │ │ ├── big.js │ │ ├── bootstrap.js │ │ ├── delta_input.js │ │ ├── group-order-form.js │ │ ├── list.delay.js │ │ ├── list.reset.js │ │ ├── list.unlist.js │ │ ├── migrate-units-form.js │ │ ├── ordering.js │ │ ├── receive-order-form.js │ │ ├── stupidtable.js │ │ ├── unit-conversion-field.js │ │ └── units-converter.js │ └── stylesheets │ │ ├── .gitkeep │ │ ├── actiontext.css │ │ ├── application.scss │ │ ├── article.scss │ │ ├── bootstrap_and_overrides.css.scss │ │ ├── datepicker.scss │ │ ├── delta_input.scss │ │ ├── group_order.scss │ │ ├── ie_hacks.css │ │ ├── list.missing.css │ │ ├── list.unlist.css │ │ ├── main.sass │ │ ├── print.scss │ │ └── token-input-bootstrappy.css ├── controllers │ ├── admin │ │ ├── bank_accounts_controller.rb │ │ ├── bank_gateways_controller.rb │ │ ├── base_controller.rb │ │ ├── configs_controller.rb │ │ ├── finances_controller.rb │ │ ├── financial_transaction_classes_controller.rb │ │ ├── financial_transaction_types_controller.rb │ │ ├── mail_delivery_status_controller.rb │ │ ├── ordergroups_controller.rb │ │ ├── supplier_categories_controller.rb │ │ ├── users_controller.rb │ │ └── workgroups_controller.rb │ ├── api │ │ └── v1 │ │ │ ├── article_categories_controller.rb │ │ │ ├── articles_controller.rb │ │ │ ├── base_controller.rb │ │ │ ├── configs_controller.rb │ │ │ ├── financial_transaction_classes_controller.rb │ │ │ ├── financial_transaction_types_controller.rb │ │ │ ├── financial_transactions_controller.rb │ │ │ ├── navigations_controller.rb │ │ │ ├── order_articles_controller.rb │ │ │ ├── orders_controller.rb │ │ │ └── user │ │ │ ├── financial_transactions_controller.rb │ │ │ ├── group_order_articles_controller.rb │ │ │ ├── ordergroup_controller.rb │ │ │ └── users_controller.rb │ ├── application_controller.rb │ ├── article_categories_controller.rb │ ├── article_units_controller.rb │ ├── articles_controller.rb │ ├── concerns │ │ ├── auth.rb │ │ ├── auth_api.rb │ │ ├── collection_scope.rb │ │ ├── foodcoop_scope.rb │ │ ├── locale.rb │ │ └── send_order_pdf.rb │ ├── deliveries_controller.rb │ ├── errors_controller.rb │ ├── finance │ │ ├── balancing_controller.rb │ │ ├── bank_accounts_controller.rb │ │ ├── bank_transactions_controller.rb │ │ ├── base_controller.rb │ │ ├── financial_links_controller.rb │ │ ├── financial_transactions_controller.rb │ │ ├── invoices_controller.rb │ │ └── ordergroups_controller.rb │ ├── foodcoop │ │ ├── ordergroups_controller.rb │ │ ├── users_controller.rb │ │ └── workgroups_controller.rb │ ├── group_order_articles_controller.rb │ ├── group_orders_controller.rb │ ├── home_controller.rb │ ├── invites_controller.rb │ ├── login_controller.rb │ ├── order_articles_controller.rb │ ├── order_comments_controller.rb │ ├── orders_controller.rb │ ├── pickups_controller.rb │ ├── sessions_controller.rb │ ├── stock_takings_controller.rb │ ├── stockit_controller.rb │ ├── styles_controller.rb │ ├── supplier_shares_controller.rb │ ├── suppliers_controller.rb │ ├── tasks_controller.rb │ └── users_controller.rb ├── documents │ ├── order_by_articles.rb │ ├── order_by_groups.rb │ ├── order_fax.rb │ └── order_matrix.rb ├── helpers │ ├── admin │ │ ├── configs_helper.rb │ │ └── ordergroups_helper.rb │ ├── application_helper.rb │ ├── article_categories_helper.rb │ ├── articles_helper.rb │ ├── deliveries_helper.rb │ ├── finance │ │ ├── balancing_helper.rb │ │ ├── invoices_helper.rb │ │ └── ordergroups_helper.rb │ ├── foodcoop_helper.rb │ ├── group_order_articles_helper.rb │ ├── group_orders_helper.rb │ ├── home_helper.rb │ ├── order_articles_helper.rb │ ├── order_comments_helper.rb │ ├── orders_helper.rb │ ├── path_helper.rb │ ├── sessions_helper.rb │ ├── shared_helper.rb │ ├── stock_takings_helper.rb │ ├── stockit_helper.rb │ ├── suppliers_helper.rb │ ├── tasks_helper.rb │ └── users_helper.rb ├── inputs │ ├── date_picker_input.rb │ ├── date_picker_time_input.rb │ └── delta_input.rb ├── javascript │ ├── application.js │ └── trix-editor-overrides.js ├── jobs │ ├── application_job.rb │ ├── notify_finished_order_job.rb │ ├── notify_negative_balance_job.rb │ └── notify_received_order_job.rb ├── mail_receivers │ └── bounce_mail_receiver.rb ├── mailers │ └── mailer.rb ├── models │ ├── application_record.rb │ ├── article.rb │ ├── article_category.rb │ ├── article_unit.rb │ ├── article_unit_ratio.rb │ ├── article_version.rb │ ├── assignment.rb │ ├── bank_account.rb │ ├── bank_gateway.rb │ ├── bank_transaction.rb │ ├── concerns │ │ ├── custom_fields.rb │ │ ├── extendable_enum.rb │ │ ├── find_each_with_order.rb │ │ ├── localize_input.rb │ │ ├── mark_as_deleted_with_name.rb │ │ └── price_calculation.rb │ ├── delivery.rb │ ├── financial_link.rb │ ├── financial_transaction.rb │ ├── financial_transaction_class.rb │ ├── financial_transaction_type.rb │ ├── group.rb │ ├── group_order.rb │ ├── group_order_article.rb │ ├── group_order_article_quantity.rb │ ├── invite.rb │ ├── invoice.rb │ ├── mail_delivery_status.rb │ ├── membership.rb │ ├── order.rb │ ├── order_article.rb │ ├── order_comment.rb │ ├── ordergroup.rb │ ├── periodic_task_group.rb │ ├── stock_article.rb │ ├── stock_change.rb │ ├── stock_event.rb │ ├── stock_taking.rb │ ├── supplier.rb │ ├── supplier_category.rb │ ├── task.rb │ ├── user.rb │ └── workgroup.rb ├── serializers │ ├── article_category_serializer.rb │ ├── article_serializer.rb │ ├── article_unit_serializer.rb │ ├── config_serializer.rb │ ├── financial_transaction_class_serializer.rb │ ├── financial_transaction_serializer.rb │ ├── financial_transaction_type_serializer.rb │ ├── group_order_article_serializer.rb │ ├── order_article_serializer.rb │ ├── order_serializer.rb │ ├── stock_article_serializer.rb │ └── user_serializer.rb ├── services │ └── supplier_sync_service.rb └── views │ ├── active_storage │ └── blobs │ │ └── _blob.html.haml │ ├── admin │ ├── bank_accounts │ │ ├── _form.html.haml │ │ └── new.js.haml │ ├── bank_gateways │ │ ├── _form.html.haml │ │ └── new.js.haml │ ├── base │ │ └── index.html.haml │ ├── configs │ │ ├── _tab_foodcoop.html.haml │ │ ├── _tab_language.html.haml │ │ ├── _tab_layout.html.haml │ │ ├── _tab_messages.html.haml │ │ ├── _tab_others.html.haml │ │ ├── _tab_payment.html.haml │ │ ├── _tab_security.html.haml │ │ ├── _tab_tasks.html.haml │ │ ├── _tabs.html.haml │ │ ├── list.html.haml │ │ └── show.html.haml │ ├── finances │ │ ├── _bank_accounts.html.haml │ │ ├── _bank_gateways.html.haml │ │ ├── _form.html.haml │ │ ├── _supplier_categories.html.haml │ │ ├── _transaction_types.html.haml │ │ ├── index.html.haml │ │ ├── update_bank_accounts.js.haml │ │ ├── update_bank_gateways.js.haml │ │ ├── update_supplier_categories.js.haml │ │ └── update_transaction_types.js.haml │ ├── financial_transaction_classes │ │ ├── _form.html.haml │ │ └── new.js.haml │ ├── financial_transaction_types │ │ ├── _form.html.haml │ │ └── new.js.haml │ ├── mail_delivery_status │ │ ├── _maildeliverystatus.html.haml │ │ ├── index.html.haml │ │ └── index.js.haml │ ├── ordergroups │ │ ├── _form.html.haml │ │ ├── _ordergroups.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── supplier_categories │ │ ├── _form.html.haml │ │ └── new.js.haml │ ├── users │ │ ├── _form.html.haml │ │ ├── _users.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ └── workgroups │ │ ├── _form.html.haml │ │ ├── _workgroups.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── article_categories │ ├── _form.html.haml │ ├── edit.html.haml │ ├── index.html.haml │ └── new.html.haml │ ├── article_units │ ├── _create_link.html.haml │ ├── _destroy_link.html.haml │ ├── _rows.html.haml │ ├── create.js.haml │ ├── destroy.js.haml │ ├── index.html.haml │ └── search.js.haml │ ├── articles │ ├── _article.html.haml │ ├── _articles.html.haml │ ├── _destroy_active_article.html.haml │ ├── _edit_all_table.html.haml │ ├── _form.html.haml │ ├── _sync.html.haml │ ├── _sync_table.html.haml │ ├── copy.js.haml │ ├── create.js.haml │ ├── destroy.js.haml │ ├── edit.html.haml │ ├── edit_all.html.haml │ ├── index.html.haml │ ├── index.js.haml │ ├── migrate_units.html.haml │ ├── new.js.haml │ ├── parse_upload.html.haml │ ├── prepare_units_migration.haml │ ├── sync.html.haml │ ├── update.js.haml │ └── upload.html.haml │ ├── deliveries │ ├── _form.html.haml │ ├── _stock_article_for_adding.html.haml │ ├── _stock_change.html.haml │ ├── _stock_change_fields.html.haml │ ├── add_stock_change.js.erb │ ├── edit.html.haml │ ├── form_on_stock_article_create.js.erb │ ├── form_on_stock_article_update.js.erb │ ├── index.html.haml │ ├── new.html.haml │ └── show.html.haml │ ├── errors │ ├── _error.html.haml │ ├── internal_server_error.html.haml │ └── not_found.html.haml │ ├── finance │ ├── balancing │ │ ├── _edit_note.html.haml │ │ ├── _edit_results_by_articles.html.haml │ │ ├── _edit_transport.html.haml │ │ ├── _group_order_articles.html.haml │ │ ├── _invoice.html.haml │ │ ├── _order_article.html.haml │ │ ├── _order_article_result.html.haml │ │ ├── _orders.html.haml │ │ ├── _summary.haml │ │ ├── confirm.html.haml │ │ ├── edit_note.js.haml │ │ ├── edit_transport.js.haml │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ ├── new.html.haml │ │ ├── new.js.haml │ │ ├── new_on_order_article_create.js.erb │ │ ├── new_on_order_article_update.js.erb │ │ ├── update_note.js.haml │ │ └── update_summary.js.haml │ ├── bank_accounts │ │ ├── _import.html.haml │ │ ├── import.html.haml │ │ ├── import.js.haml │ │ └── index.html.haml │ ├── bank_transactions │ │ ├── _transactions.html.haml │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ └── show.html.haml │ ├── financial_links │ │ ├── _index_bank_transaction.html.haml │ │ ├── _index_financial_transaction.html.haml │ │ ├── _index_invoice.html.haml │ │ ├── _new_financial_transaction.html.haml │ │ ├── incomplete.html.haml │ │ ├── index_bank_transaction.js.haml │ │ ├── index_financial_transaction.js.haml │ │ ├── index_invoice.js.haml │ │ ├── new_financial_transaction.js.haml │ │ └── show.html.haml │ ├── financial_transactions │ │ ├── _order_note.html.haml │ │ ├── _ordergroup.haml │ │ ├── _transactions.html.haml │ │ ├── _transactions_search.html.haml │ │ ├── index.html.haml │ │ ├── index.js.erb │ │ ├── index_collection.html.haml │ │ ├── index_collection.js.erb │ │ ├── new.html.haml │ │ └── new_collection.html.haml │ ├── index.html.haml │ ├── invoices │ │ ├── _form.html.haml │ │ ├── _form_js.html.haml │ │ ├── _invoices.html.haml │ │ ├── delete_attachment.js.erb │ │ ├── edit.html.haml │ │ ├── form_on_supplier_id_change.js.erb │ │ ├── index.html.haml │ │ ├── index.js.haml │ │ ├── new.html.haml │ │ ├── show.html.haml │ │ └── unpaid.html.haml │ └── ordergroups │ │ ├── _ordergroups.html.haml │ │ ├── index.html.haml │ │ └── index.js.haml │ ├── foodcoop │ ├── ordergroups │ │ ├── _ordergroups.html.haml │ │ ├── index.html.haml │ │ └── index.js.haml │ ├── users │ │ ├── _users.html.haml │ │ ├── index.html.haml │ │ └── index.js.haml │ └── workgroups │ │ ├── _workgroup.html.haml │ │ ├── edit.html.haml │ │ └── index.html.haml │ ├── group_order_articles │ ├── _form.html.haml │ ├── create.js.erb │ ├── new.js.erb │ └── update.js.erb │ ├── group_orders │ ├── _form.html.haml │ ├── _orders.html.haml │ ├── _switch_order.html.haml │ ├── archive.html.haml │ ├── archive.js.haml │ ├── edit.html.haml │ ├── index.html.haml │ ├── new.html.haml │ └── show.html.haml │ ├── home │ ├── _apple_bar.html.haml │ ├── _start_nav.haml │ ├── index.html.haml │ ├── ordergroup.html.haml │ ├── ordergroup.js.haml │ ├── profile.html.haml │ └── reference_calculator.haml │ ├── invites │ ├── _modal_form.html.haml │ ├── create.js.haml │ ├── new.html.haml │ └── new.js.haml │ ├── kaminari │ ├── _first_page.html.haml │ ├── _gap.html.haml │ ├── _last_page.html.haml │ ├── _next_page.html.haml │ ├── _page.html.haml │ ├── _paginator.html.haml │ └── _prev_page.html.haml │ ├── layouts │ ├── _footer.html.haml │ ├── _header.html.haml │ ├── action_text │ │ └── contents │ │ │ └── _content.html.erb │ ├── application.html.haml │ ├── email.html.haml │ ├── email.text.haml │ └── login.html.haml │ ├── login │ ├── accept_invitation.html.haml │ ├── forgot_password.html.haml │ └── new_password.html.haml │ ├── mailer │ ├── invite.text.haml │ ├── negative_balance.text.haml │ ├── not_enough_users_assigned.text.haml │ ├── order_received.text.haml │ ├── order_result.text.haml │ ├── order_result_supplier.text.haml │ ├── reset_password.text.haml │ ├── upcoming_tasks.text.haml │ └── welcome.text.haml │ ├── order_articles │ ├── _edit.html.haml │ ├── _new.html.haml │ ├── create.js.erb │ ├── destroy.js.haml │ ├── edit.js.haml │ ├── new.js.haml │ └── update.js.erb │ ├── order_comments │ ├── _form.html.haml │ ├── create.js.haml │ └── new.js.haml │ ├── ordergroups │ ├── edit.html.haml │ └── index.html.haml │ ├── orders │ ├── _articles.html.haml │ ├── _edit_amount.html.haml │ ├── _edit_amounts.html.haml │ ├── _form.html.haml │ ├── _orders.html.haml │ ├── _show_js.html.haml │ ├── add_article.js.erb │ ├── edit.html.haml │ ├── index.html.haml │ ├── index.js.erb │ ├── new.html.haml │ ├── receive.html.haml │ ├── receive_on_order_article_create.js.erb │ ├── receive_on_order_article_update.js.erb │ ├── show.html.haml │ └── show.js.erb │ ├── pickups │ └── index.html.haml │ ├── sessions │ └── new.html.haml │ ├── shared │ ├── _alert_success.haml │ ├── _article_fields_price.html.haml │ ├── _article_fields_units.html.haml │ ├── _article_unit_ratio.haml │ ├── _article_version_info.html.haml │ ├── _base_errors.haml │ ├── _comments.haml │ ├── _custom_form_fields.html.haml │ ├── _group.html.haml │ ├── _group_form_fields.html.haml │ ├── _open_orders.html.haml │ ├── _order_download_button.html.haml │ ├── _task_list.haml │ ├── _user_form_fields.html.haml │ ├── _workgroup_members.haml │ ├── alert.js.erb │ ├── articles_by │ │ ├── _article_single.html.haml │ │ ├── _article_single_goa.html.haml │ │ ├── _articles.html.haml │ │ ├── _common.html.haml │ │ ├── _group_single.html.haml │ │ ├── _group_single_goa.html.haml │ │ └── _groups.html.haml │ └── js_templates │ │ └── _unit_conversion_popover_template.haml │ ├── stock_takings │ ├── _stock_change.html.haml │ ├── _stock_takings.html.haml │ ├── edit.html.haml │ ├── index.html.haml │ ├── index.js.haml │ ├── new.html.haml │ ├── new_on_stock_article_create.js.erb │ └── show.html.haml │ ├── stockit │ ├── _destroy_fail.js.haml │ ├── _form.html.haml │ ├── _stock_article.html.haml │ ├── _stock_article_details.html.haml │ ├── copy.js.erb │ ├── create.js.erb │ ├── derive.js.erb │ ├── destroy.js.erb │ ├── edit.js.erb │ ├── index.html.haml │ ├── index_on_stock_article_create.js.erb │ ├── index_on_stock_article_update.js.erb │ ├── new.js.erb │ ├── show.html.haml │ ├── show_on_stock_article_update.js.erb │ └── update.js.erb │ ├── supplier_shares │ ├── _share_link.html.haml │ └── update.js.haml │ ├── suppliers │ ├── _form.html.haml │ ├── _import_search_results.haml │ ├── edit.html.haml │ ├── index.html.haml │ ├── new.html.haml │ ├── remote_articles.js.haml │ └── show.html.haml │ ├── tasks │ ├── _archive_tasks.html.haml │ ├── _form.html.haml │ ├── _form_javascript.html.haml │ ├── _form_sidebar.html.haml │ ├── _nav.haml │ ├── archive.haml │ ├── archive.js.haml │ ├── edit.haml │ ├── index.haml │ ├── new.haml │ ├── show.haml │ ├── user.html.haml │ └── workgroup.haml │ └── workgroups │ ├── edit.html.haml │ └── index.html.haml ├── bin ├── autospec ├── bundle ├── importmap ├── mailcatcher ├── rails ├── rake ├── resque ├── resque-web ├── rspec ├── rubocop ├── setup ├── test ├── update └── yarn ├── config.ru ├── config ├── app_config.yml.SAMPLE ├── application.rb ├── boot.rb ├── database.yml.MySQL_SAMPLE ├── database.yml.SQLite_SAMPLE ├── environment.rb ├── environments │ ├── development.rb.SAMPLE │ ├── production.rb │ └── test.rb ├── i18n-js.yml ├── importmap.rb ├── initializers │ ├── 01_load_app_config.rb │ ├── active_job_select_foodcoop.rb │ ├── active_model_serializers.rb │ ├── active_storage_foodcoop_path.rb │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── attribute_normalizer.rb │ ├── backtrace_silencers.rb │ ├── bullet.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── cors.rb │ ├── currency_display.rb │ ├── doorkeeper.rb │ ├── exception_notification.rb │ ├── extensions.rb │ ├── filter_parameter_logging.rb │ ├── gaffe.rb │ ├── inflections.rb │ ├── mail_receiver.rb │ ├── mime_types.rb │ ├── new_rails_defaults.rb │ ├── permissions_policy.rb │ ├── prawn_pdf.rb │ ├── rack.rb │ ├── resque.rb │ ├── rswag_api.rb │ ├── rswag_ui.rb │ ├── ruby_units.rb │ ├── secret_token.rb │ ├── session_store.rb │ ├── simple_form.rb │ ├── simple_form_bootstrap.rb │ ├── simple_navigation.rb │ ├── time_formats.rb │ ├── wrap_parameters.rb │ └── zeitwerk.rb ├── locales │ ├── de.yml │ ├── en.yml │ ├── es.yml │ ├── fr.yml │ ├── nl.yml │ ├── overrides.yml │ └── tr.yml ├── navigation.rb ├── puma.rb ├── routes.rb ├── schedule.rb ├── spring.rb ├── storage.yml.SAMPLE └── units-of-measure │ ├── locales │ ├── unece_de.yml │ ├── unece_en.yml │ ├── unece_es.yml │ ├── unece_fr.yml │ ├── unece_nl.yml │ └── unece_tr.yml │ ├── translations_piece.csv │ ├── translations_scalar-de.csv │ ├── translations_scalar-en.csv │ ├── translations_scalar-nl.csv │ ├── un-ece-20-remastered.yml │ ├── un-ece-20.yml │ └── un-ece-21.yml ├── crowdin.yml ├── db ├── migrate │ ├── 001_create_users.rb │ ├── 002_create_groups.rb │ ├── 003_create_suppliers.rb │ ├── 004_create_article_meta.rb │ ├── 005_create_financial_transactions.rb │ ├── 006_create_articles.rb │ ├── 007_create_article_prices.rb │ ├── 008_create_orders.rb │ ├── 009_create_order_results.rb │ ├── 010_user_password_reset.rb │ ├── 011_create_comments.rb │ ├── 012_create_order_clearing.rb │ ├── 013_add_messaging.rb │ ├── 014_create_tasks.rb │ ├── 015_change_result_quantities.rb │ ├── 016_add_shared_lists_connection.rb │ ├── 017_add_min_order_quantity.rb │ ├── 018_create_invites.rb │ ├── 019_remove_uniqueness_of_article_name.rb │ ├── 020_add_users_last_login.rb │ ├── 021_remove_table_article_prices.rb │ ├── 022_add_required_user_for_task.rb │ ├── 023_new_wording.rb │ ├── 024_add_deposit_defaults.rb │ ├── 025_extend_comments.rb │ ├── 20090120184410_road_to_version_three.rb │ ├── 20090317175355_add_profit_to_orders.rb │ ├── 20090325175756_create_pages.foodsoft_wiki_engine.rb │ ├── 20090405131156_modify_group_order_article_result.rb │ ├── 20090731132547_add_stats_to_groups.rb │ ├── 20090811144901_add_weekly_to_tasks.rb │ ├── 20090812110010_add_note_to_deliveries.rb │ ├── 20090907120012_add_missing_indexes.rb │ ├── 20110507184920_add_duration_to_tasks.rb │ ├── 20110507192928_add_task_duration_to_workgroups.rb │ ├── 20120512211613_add_order_indexes.rb │ ├── 20120622094337_add_next_weekly_tasks_number_to_workgroups.rb │ ├── 20120929155541_add_ignore_apple_restriction_to_groups.rb │ ├── 20121112093327_add_created_by_user_id_to_orders.rb │ ├── 20121216180646_remove_assigned_from_tasks.rb │ ├── 20121230142516_remove_account_updated_from_ordergroups.rb │ ├── 20130615073715_create_periodic_task_groups.rb │ ├── 20130622095040_move_weekly_tasks.rb │ ├── 20130624084223_remove_weekly_from_tasks.rb │ ├── 20130624085246_remove_weekly_task_from_groups.rb │ ├── 20130702113610_update_group_order_totals.rb │ ├── 20130718183100_create_settings.rb │ ├── 20130718183101_migrate_user_settings.rb │ ├── 20130920201529_allow_missing_nick.rb │ ├── 20130930132511_add_quantities_to_order_article.rb │ ├── 20140102170431_add_result_computed_to_group_order_articles.rb │ ├── 20140318173000_delete_empty_group_order_articles.rb │ ├── 20140521142651_add_sync_method_to_supplier.rb │ ├── 20140921104907_remove_stale_memberships.rb │ ├── 20141211210719_increase_account_balance_precision.rb │ ├── 20150227161931_add_replyto_and_groupid_to_messages.rb │ ├── 20150301000000_add_last_activity_to_user.rb │ ├── 20150923190747_add_boxfill_to_order.rb │ ├── 20160217115252_add_deleted_at_to_user.rb │ ├── 20160217124256_add_created_by_user_id_to_invoice.rb │ ├── 20160217134742_change_invoice_relation.rb │ ├── 20160217152621_add_pickup_to_order.rb │ ├── 20160217164552_add_break_to_group.rb │ ├── 20160217194036_add_role_invoices_to_group.rb │ ├── 20160218151041_add_attachment_to_invoice.rb │ ├── 20160219123220_create_financial_transaction_class_and_types.rb │ ├── 20160220000000_create_documents.foodsoft_documents_engine.rb │ ├── 20160222000000_create_bank_accounts_and_transactions.rb │ ├── 20160224201529_allow_stock_group_order.rb │ ├── 20160226000000_add_email_to_message.foodsoft_messages_engine.rb │ ├── 20160309153440_create_doorkeeper_tables.rb │ ├── 20161001000000_add_iban_to_supplier_and_user.rb │ ├── 20170801000000_create_mail_delivery_status.rb │ ├── 20171001000000_add_last_sent_mail_to_order.rb │ ├── 20171001020000_add_end_action_to_order.rb │ ├── 20171002000000_create_financial_links.rb │ ├── 20171105000000_add_parent_to_document.foodsoft_documents_engine.rb │ ├── 20171111000000_add_role_pickups_to_group.rb │ ├── 20171201000000_add_name_short_to_financial_transaction_type.rb │ ├── 20181013195028_add_confidential_to_applications.rb │ ├── 20181110000000_create_polls.foodsoft_polls_engine.rb │ ├── 20181120000000_increase_choices_size.foodsoft_polls_engine.rb │ ├── 20181201000000_create_printer_jobs.foodsoft_printer_engine.rb │ ├── 20181201000100_create_message_recipients.foodsoft_messages.rb │ ├── 20181201000200_add_deleted_to_financial_transaction_type.rb │ ├── 20181201000210_add_group_order_to_financial_transaction.rb │ ├── 20181201000220_add_transport_to_order.rb │ ├── 20181201000300_allow_emtpy_ordergroup_in_financial_transaction.rb │ ├── 20181201000301_change_ordergroup_default_in_financial_transaction.rb │ ├── 20181201000302_change_stock_supplier_to_null_in_order.rb │ ├── 20181201000305_ensure_article_for_article_price.rb │ ├── 20181201000400_create_supplier_categories.rb │ ├── 20181203000000_create_links.foodsoft_links.rb │ ├── 20181204000000_clear_invalid_invoices_from_orders.rb │ ├── 20181204010000_change_marked_as_deleted_names.rb │ ├── 20181204060000_change_delivered_on_to_date.rb │ ├── 20181204070000_create_stock_events.rb │ ├── 20181205000000_add_user_to_task.rb │ ├── 20181205010000_add_bank_account_to_financial_transaction_type.rb │ ├── 20190100000006_change_order_article_result_types.rb │ ├── 20190100000007_add_ignore_for_account_balance_to_financial_transaction_classes.rb │ ├── 20190100000008_add_bank_account_to_supplier_category.rb │ ├── 20190100000009_create_bank_gateways.rb │ ├── 20190101000000_create_active_storage_tables.active_storage.rb │ ├── 20210205090257_introduce_received_state_in_orders.rb │ ├── 20230106144438_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20230106144439_create_active_storage_variant_records.active_storage.rb │ ├── 20230106144440_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb │ ├── 20230209105256_create_action_text_tables.action_text.rb │ ├── 20230215085312_migrate_message_body_to_action_text.rb │ ├── 20230915093041_add_payment_to_financial_transaction.rb │ ├── 20240126111615_move_attachment_to_active_storage.rb │ ├── 20240306141647_move_documents_to_active_storage.rb │ ├── 20240404004950_add_use_financial_links_setting.rb │ ├── 20240410093313_change_bank_account_desc.rb │ ├── 20240726083740_alter_articles_add_versioning.rb │ ├── 20240726083741_alter_articles_add_more_unit_logic.rb │ ├── 20240726083742_alter_suppliers_sharing_fields.rb │ ├── 20240726083743_create_article_units.rb │ ├── 20240726083744_add_unit_migration_completed_to_suppliers.rb │ ├── 20250322103203_fix_schema_inconsistent_with_migration_history.rb │ ├── 20250519093453_rename_order_timestamp_and_add_remote_order_fields_to_supplier.rb │ ├── 20250523191049_add_deleted_at_to_article_category.rb │ └── 20250528114335_add_remote_auto_sync_to_suppliers.rb ├── schema.rb ├── seeds.rb └── seeds │ ├── minimal.seeds.rb │ ├── seed_helper.rb │ └── small.en.seeds.rb ├── doc ├── API.md ├── BESTELLEN.md ├── SETUP_DEVELOPMENT.md ├── SETUP_DEVELOPMENT_DOCKER.md ├── SETUP_DEVELOPMENT_GITPOD.md ├── SETUP_PRODUCTION.md ├── article_units_fork_architecture_changes.md ├── building blocks │ └── finance │ │ ├── finance.md │ │ └── finance.png └── design_patterns │ └── publish_subscribe.md ├── docker-compose-dev.yml ├── docker-compose.ci.yml ├── docker-entrypoint.sh ├── lib ├── api │ └── errors.rb ├── apple_bar.rb ├── article_units_lib.rb ├── articles_csv.rb ├── bank_account_connector.rb ├── bank_account_connector_external.rb ├── bank_account_information_importer.rb ├── bank_transaction_reference.rb ├── bank_transactions_csv.rb ├── date_time_attribute_validate.rb ├── financial_transactions_csv.rb ├── foodsoft │ └── expansion_variables.rb ├── foodsoft_config.rb ├── foodsoft_date_util.rb ├── foodsoft_file.rb ├── foodsoft_mail_receiver.rb ├── invoices_csv.rb ├── order_csv.rb ├── order_pdf.rb ├── order_txt.rb ├── ordergroups_csv.rb ├── render_csv.rb ├── render_pdf.rb ├── spreadsheet_file.rb ├── tasks │ ├── .gitkeep │ ├── foodsoft.rake │ ├── foodsoft_setup.rake │ ├── multicoops.rake │ ├── resque.rake │ ├── rspec.rake │ ├── seeds.rake │ └── units.rake ├── templates │ └── haml │ │ └── scaffold │ │ └── _form.html.haml ├── token_verifier.rb └── users_csv.rb ├── plugins ├── README.md ├── b85 │ ├── README.md │ ├── Rakefile │ ├── config │ │ └── locales │ │ │ ├── de.yml │ │ │ └── en.yml │ ├── doc │ │ ├── Bestellung_Lieferavis_Schnittstelle_2025.pdf │ │ └── Biofakt B85 BNN-3.0_Bestellungen.pdf │ ├── foodsoft_b85.gemspec │ ├── lib │ │ ├── foodsoft_b85.rb │ │ └── foodsoft_b85 │ │ │ ├── engine.rb │ │ │ ├── order_b85.rb │ │ │ ├── order_extensions.rb │ │ │ ├── supplier_extensions.rb │ │ │ └── version.rb │ └── spec │ │ ├── lib │ │ └── foodsoft_b85 │ │ │ └── order_b85_spec.rb │ │ └── models │ │ └── order_ftp_b85_spec.rb ├── current_orders │ ├── README.md │ ├── app │ │ ├── controllers │ │ │ ├── current_orders │ │ │ │ ├── articles_controller.rb │ │ │ │ ├── group_orders_controller.rb │ │ │ │ ├── ordergroups_controller.rb │ │ │ │ └── orders_controller.rb │ │ │ └── current_orders_controller.rb │ │ ├── documents │ │ │ ├── multiple_orders_by_articles.rb │ │ │ └── multiple_orders_by_groups.rb │ │ ├── helpers │ │ │ └── current_orders_helper.rb │ │ ├── overrides │ │ │ ├── admin │ │ │ │ └── configs │ │ │ │ │ └── _tab_others │ │ │ │ │ └── add_current_orders.html.haml.deface │ │ │ ├── group_orders │ │ │ │ └── show │ │ │ │ │ └── add_pdf_download.html.haml.deface │ │ │ └── orders │ │ │ │ └── index │ │ │ │ └── add_combined_button.html.haml.deface │ │ └── views │ │ │ └── current_orders │ │ │ ├── articles │ │ │ ├── _actions.html.haml │ │ │ ├── _article.html.haml │ │ │ ├── _article_info.html.haml │ │ │ ├── _articles.html.haml │ │ │ ├── _form.html.haml │ │ │ ├── _ordergroups.html.haml │ │ │ ├── index.html.haml │ │ │ ├── index.js.erb │ │ │ ├── show.html.haml │ │ │ ├── show.js.erb │ │ │ └── show_on_group_order_article_create.js.erb │ │ │ ├── group_orders │ │ │ ├── _payment_bar.html.haml │ │ │ ├── _result.html.haml │ │ │ └── index.html.haml │ │ │ ├── ordergroups │ │ │ ├── _article.html.haml │ │ │ ├── _articles.html.haml │ │ │ ├── _form.html.haml │ │ │ ├── _payment_bar.html.haml │ │ │ ├── index.html.haml │ │ │ ├── show.html.haml │ │ │ ├── show.js.erb │ │ │ ├── show_on_group_order_article_create.js.erb │ │ │ └── show_on_group_order_article_update.js.erb │ │ │ └── orders │ │ │ └── receive.html.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ ├── es.yml │ │ │ ├── fr.yml │ │ │ ├── nl.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── foodsoft_current_orders.gemspec │ └── lib │ │ ├── foodsoft_current_orders.rb │ │ └── foodsoft_current_orders │ │ ├── engine.rb │ │ └── version.rb ├── discourse │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ ├── discourse_controller.rb │ │ │ ├── discourse_login_controller.rb │ │ │ └── discourse_sso_controller.rb │ │ └── overrides │ │ │ └── sessions │ │ │ └── new │ │ │ └── insert_link.html.haml.deface │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ ├── es.yml │ │ │ ├── fr.yml │ │ │ ├── nl.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── foodsoft_discourse.gemspec │ └── lib │ │ ├── foodsoft_discourse.rb │ │ └── foodsoft_discourse │ │ ├── engine.rb │ │ ├── redirect_to_login.rb │ │ └── version.rb ├── documents │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── documents_controller.rb │ │ ├── models │ │ │ └── document.rb │ │ ├── overrides │ │ │ └── admin │ │ │ │ └── configs │ │ │ │ └── _tab_others │ │ │ │ └── add_documents_config.html.haml.deface │ │ └── views │ │ │ └── documents │ │ │ ├── _documents.html.haml │ │ │ ├── _form.html.haml │ │ │ ├── _move.html.haml │ │ │ ├── index.html.haml │ │ │ ├── index.js.haml │ │ │ ├── move.js.haml │ │ │ └── new.js.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ ├── es.yml │ │ │ ├── fr.yml │ │ │ ├── nl.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── db │ │ └── migrate │ │ │ ├── 20160220000000_create_documents.rb │ │ │ ├── 20171105000000_add_parent_to_document.rb │ │ │ └── 20240306141647_move_documents_to_active_storage.rb │ ├── foodsoft_documents.gemspec │ └── lib │ │ ├── foodsoft_documents.rb │ │ └── foodsoft_documents │ │ ├── engine.rb │ │ └── version.rb ├── links │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ ├── admin │ │ │ │ └── links_controller.rb │ │ │ └── links_controller.rb │ │ ├── models │ │ │ └── link.rb │ │ └── views │ │ │ └── admin │ │ │ └── links │ │ │ ├── _form.html.haml │ │ │ ├── _links.html.haml │ │ │ ├── edit.js.haml │ │ │ ├── index.html.haml │ │ │ └── update_links.js.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── db │ │ └── migrate │ │ │ └── 20181203000000_create_links.rb │ ├── foodsoft_links.gemspec │ └── lib │ │ ├── foodsoft_links.rb │ │ └── foodsoft_links │ │ ├── engine.rb │ │ └── version.rb ├── messages │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ ├── admin │ │ │ │ └── messagegroups_controller.rb │ │ │ ├── message_threads_controller.rb │ │ │ ├── messagegroups_controller.rb │ │ │ └── messages_controller.rb │ │ ├── helpers │ │ │ └── messages_helper.rb │ │ ├── jobs │ │ │ └── deliver_message_job.rb │ │ ├── mail_receivers │ │ │ └── messages_mail_receiver.rb │ │ ├── mailers │ │ │ └── messages_mailer.rb │ │ ├── models │ │ │ ├── message.rb │ │ │ ├── message_recipient.rb │ │ │ └── messagegroup.rb │ │ ├── overrides │ │ │ ├── admin │ │ │ │ ├── configs │ │ │ │ │ └── _tab_messages │ │ │ │ │ │ └── add_config.html.haml.deface │ │ │ │ ├── ordergroups │ │ │ │ │ └── show │ │ │ │ │ │ └── new_message.html.haml.deface │ │ │ │ ├── users │ │ │ │ │ └── show │ │ │ │ │ │ └── new_message.html.haml.deface │ │ │ │ └── workgroups │ │ │ │ │ └── show │ │ │ │ │ └── new_message.html.haml.deface │ │ │ ├── foodcoop │ │ │ │ ├── ordergroups │ │ │ │ │ └── _ordergroups │ │ │ │ │ │ └── new_message.html.haml.deface │ │ │ │ ├── users │ │ │ │ │ └── _users │ │ │ │ │ │ └── new_message.html.haml.deface │ │ │ │ └── workgroups │ │ │ │ │ └── _workgroup │ │ │ │ │ └── new_message.html.haml.deface │ │ │ ├── home │ │ │ │ ├── _start_nav │ │ │ │ │ └── new_message.html.haml.deface │ │ │ │ └── index │ │ │ │ │ └── latest_public_messages_index.html.haml.deface │ │ │ ├── orders │ │ │ │ └── show │ │ │ │ │ └── add_message_button.html.haml.deface │ │ │ └── shared │ │ │ │ └── _user_form_fields │ │ │ │ └── add_messages_prefs.html.haml.deface │ │ └── views │ │ │ ├── admin │ │ │ └── messagegroups │ │ │ │ ├── _form.html.haml │ │ │ │ ├── _messagegroups.html.haml │ │ │ │ ├── edit.html.haml │ │ │ │ ├── index.html.haml │ │ │ │ ├── index.js.haml │ │ │ │ ├── new.html.haml │ │ │ │ └── show.html.haml │ │ │ ├── message_threads │ │ │ ├── _groupmessage_threads.html.haml │ │ │ ├── _message_threads.html.haml │ │ │ ├── index.html.haml │ │ │ ├── show.haml │ │ │ └── show.js.haml │ │ │ ├── messagegroups │ │ │ ├── _messagegroup.html.haml │ │ │ └── index.html.haml │ │ │ ├── messages │ │ │ ├── _actionbar.haml │ │ │ ├── _messages.html.haml │ │ │ ├── index.html.haml │ │ │ ├── index.js.haml │ │ │ ├── new.haml │ │ │ ├── show.haml │ │ │ └── thread.haml │ │ │ └── messages_mailer │ │ │ ├── foodsoft_message.html.haml │ │ │ └── foodsoft_message.text.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ ├── es.yml │ │ │ ├── fr.yml │ │ │ ├── nl.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── db │ │ └── migrate │ │ │ ├── 20090120184410_create_messages.rb.skip │ │ │ └── 20160226000000_add_email_to_message.rb │ ├── foodsoft_messages.gemspec │ └── lib │ │ ├── foodsoft_messages.rb │ │ └── foodsoft_messages │ │ ├── engine.rb │ │ ├── mail_receiver.rb │ │ ├── user_link.rb │ │ └── version.rb ├── mollie │ ├── .gitignore │ ├── Gemfile │ ├── LICENSE │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── payments │ │ │ │ └── mollie_controller.rb │ │ ├── overrides │ │ │ ├── admin │ │ │ │ └── configs │ │ │ │ │ └── _tab_others │ │ │ │ │ └── add_config.html.haml.deface │ │ │ └── home │ │ │ │ ├── index │ │ │ │ └── new_payment_link.html.haml.deface │ │ │ │ └── ordergroup │ │ │ │ └── new_payment_button.html.haml.deface │ │ └── views │ │ │ └── payments │ │ │ └── mollie │ │ │ ├── _form.html.haml │ │ │ └── new.html.haml │ ├── config │ │ ├── locales │ │ │ ├── en.yml │ │ │ └── nl.yml │ │ └── routes.rb │ ├── foodsoft_mollie.gemspec │ ├── lib │ │ ├── foodsoft_mollie.rb │ │ └── foodsoft_mollie │ │ │ ├── engine.rb │ │ │ └── version.rb │ └── script │ │ └── rails ├── polls │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ └── polls_controller.rb │ │ ├── models │ │ │ ├── poll.rb │ │ │ ├── poll_choice.rb │ │ │ └── poll_vote.rb │ │ ├── overrides │ │ │ └── admin │ │ │ │ └── configs │ │ │ │ └── _tab_others │ │ │ │ └── add_polls_config.html.haml.deface │ │ └── views │ │ │ └── polls │ │ │ ├── _choice.haml │ │ │ ├── _form.html.haml │ │ │ ├── _polls.html.haml │ │ │ ├── edit.html.haml │ │ │ ├── index.html.haml │ │ │ ├── index.js.haml │ │ │ ├── new.html.haml │ │ │ ├── show.html.haml │ │ │ └── vote.html.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── db │ │ └── migrate │ │ │ ├── 20181110000000_create_polls.rb │ │ │ └── 20181120000000_increase_choices_size.rb │ ├── foodsoft_polls.gemspec │ └── lib │ │ ├── foodsoft_polls.rb │ │ └── foodsoft_polls │ │ ├── engine.rb │ │ └── version.rb ├── printer │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── controllers │ │ │ ├── printer_controller.rb │ │ │ └── printer_jobs_controller.rb │ │ ├── models │ │ │ ├── printer_job.rb │ │ │ └── printer_job_update.rb │ │ ├── overrides │ │ │ ├── admin │ │ │ │ └── configs │ │ │ │ │ └── _tab_others │ │ │ │ │ └── add_printer_config.html.haml.deface │ │ │ └── orders │ │ │ │ └── show │ │ │ │ └── add_print_button.html.haml.deface │ │ └── views │ │ │ └── printer_jobs │ │ │ ├── _jobs.html.haml │ │ │ ├── index.html.haml │ │ │ ├── index.js.haml │ │ │ └── show.html.haml │ ├── config │ │ ├── locales │ │ │ ├── de.yml │ │ │ ├── en.yml │ │ │ └── tr.yml │ │ └── routes.rb │ ├── db │ │ └── migrate │ │ │ └── 20181201000000_create_printer_jobs.rb │ ├── foodsoft_printer.gemspec │ └── lib │ │ ├── foodsoft_printer.rb │ │ └── foodsoft_printer │ │ ├── engine.rb │ │ ├── order_printer_jobs.rb │ │ └── version.rb ├── uservoice │ ├── README.md │ ├── foodsoft_uservoice.gemspec │ └── lib │ │ ├── foodsoft_uservoice.rb │ │ └── foodsoft_uservoice │ │ ├── engine.rb │ │ └── version.rb └── wiki │ ├── README.md │ ├── Rakefile │ ├── app │ ├── assets │ │ └── images │ │ │ └── icons │ │ │ ├── feed-icon-14x14.png │ │ │ └── feed-icon-28x28.png │ ├── controllers │ │ └── pages_controller.rb │ ├── helpers │ │ └── pages_helper.rb │ ├── models │ │ └── page.rb │ ├── overrides │ │ ├── admin │ │ │ └── configs │ │ │ │ └── _tab_others │ │ │ │ └── add_wiki_config.html.haml.deface │ │ ├── home │ │ │ └── index │ │ │ │ └── dashboard.html.haml.deface │ │ └── sessions │ │ │ └── new │ │ │ └── public_frontpage.html.haml.deface │ └── views │ │ └── pages │ │ ├── _body.html.haml │ │ ├── _form.html.haml │ │ ├── _page_list_item.html.haml │ │ ├── _site_map.html.haml │ │ ├── _title_list.html.haml │ │ ├── all.html.haml │ │ ├── all.rss.builder │ │ ├── diff.html.haml │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ ├── show.html.haml │ │ ├── variables.html.haml │ │ └── version.html.haml │ ├── config │ ├── locales │ │ ├── de.yml │ │ ├── en.yml │ │ ├── es.yml │ │ ├── fr.yml │ │ ├── nl.yml │ │ └── tr.yml │ └── routes.rb │ ├── db │ └── migrate │ │ └── 20090325175756_create_pages.rb │ ├── foodsoft_wiki.gemspec │ └── lib │ ├── foodsoft_wiki.rb │ └── foodsoft_wiki │ ├── engine.rb │ ├── mailer.rb │ ├── version.rb │ └── wiki_parser.rb ├── proc-start ├── public ├── 404.html ├── 406-unsupported-browser.html ├── 422.html ├── 500.html ├── 503.html ├── apple-touch-icon-114x114.png ├── apple-touch-icon-120x120.png ├── apple-touch-icon-144x144.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-57x57.png ├── apple-touch-icon-72x72.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon.png ├── favicon.ico └── robots.txt ├── publiccode.yml ├── script ├── list_databases └── rails ├── spec ├── app_config.yml ├── controllers │ ├── articles_controller_spec.rb │ ├── finance │ │ └── ordergroups_controller_spec.rb │ ├── home_controller_spec.rb │ └── supplier_shares_controller_spec.rb ├── factories │ ├── article.rb │ ├── article_category.rb │ ├── article_unit.rb │ ├── article_unit_ratio.rb │ ├── article_version.rb │ ├── bank_transaction_type.rb │ ├── delivery.rb │ ├── doorkeeper.rb │ ├── financial_transaction.rb │ ├── financial_transaction_type.rb │ ├── group_order.rb │ ├── group_order_article.rb │ ├── group_order_article_quantity.rb │ ├── invoice.rb │ ├── order.rb │ ├── supplier.rb │ └── user.rb ├── fixtures │ ├── foodsoft_file_01.csv │ ├── foodsoft_file_01.ods │ ├── foodsoft_file_01.xls │ ├── foodsoft_file_01.xlsx │ └── foodsoft_file_02.csv ├── helpers │ └── articles_helper_spec.rb ├── i18n_spec.rb ├── integration │ ├── article_units_spec.rb │ ├── articles_spec.rb │ ├── balancing_spec.rb │ ├── config_spec.rb │ ├── home_spec.rb │ ├── login_spec.rb │ ├── order_spec.rb │ ├── product_distribution_example_spec.rb │ ├── receive_spec.rb │ ├── session_spec.rb │ └── supplier_spec.rb ├── lib │ ├── article_units_lib_spec.rb │ ├── bank_account_information_importer_spec.rb │ ├── bank_transaction_reference_spec.rb │ ├── foodsoft_config_spec.rb │ ├── foodsoft_mail_receiver_spec.rb │ ├── order_txt_csv_spec.rb │ └── token_verifier_spec.rb ├── models │ ├── article_category_spec.rb │ ├── article_spec.rb │ ├── article_version_spec.rb │ ├── bank_transaction_spec.rb │ ├── delivery_spec.rb │ ├── financial_transaction_spec.rb │ ├── group_order_article_spec.rb │ ├── group_order_spec.rb │ ├── order_article_spec.rb │ ├── order_spec.rb │ ├── ordergroup_spec.rb │ ├── supplier_spec.rb │ └── user_spec.rb ├── rake │ └── tasks_foodsoft_spec.rb ├── requests │ └── api │ │ └── v1 │ │ ├── article_categories_controller_spec.rb │ │ ├── configs_controller_spec.rb │ │ ├── financial_transaction_classes_controller_spec.rb │ │ ├── financial_transaction_types_controller_spec.rb │ │ ├── financial_transactions_controller_spec.rb │ │ ├── navigations_controller_spec.rb │ │ ├── order_articles_controller_spec.rb │ │ ├── orders_controller_spec.rb │ │ ├── shared_suppliers │ │ └── articles_controller_spec.rb │ │ └── user │ │ ├── financial_transactions_spec.rb │ │ ├── group_order_articles_spec.rb │ │ └── users_spec.rb ├── services │ └── supplier_sync_service_spec.rb ├── spec_helper.rb ├── support │ ├── active_record_helper.rb │ ├── api_helper.rb │ ├── api_oauth.rb │ ├── coverage.rb │ ├── factory_bot.rb │ ├── faker.rb │ ├── integration.rb │ ├── session_helper.rb │ └── spec_test_helper.rb └── swagger_helper.rb ├── tmp └── .gitignore └── vendor ├── README.md ├── assets ├── fonts │ ├── OpenSans-Bold.ttf │ ├── OpenSans-BoldItalic.ttf │ ├── OpenSans-Italic.ttf │ └── OpenSans-Regular.ttf └── javascripts │ └── touchclick.js └── javascript └── .keep /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "jquery": true, 5 | "es6": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "ecmaVersion": 6 10 | }, 11 | "rules": { 12 | "no-unused-vars": ["error", { "vars": "local" }] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Fixes line endings for Windows (Docker) environment, which are by default converted to crlf 2 | * text=auto 3 | *.sh text eol=lf 4 | proc-start text eol=lf 5 | Rakefile text eol=lf 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Other Issue 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/workflows/rubocop.yml: -------------------------------------------------------------------------------- 1 | name: RuboCop 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout source code 11 | uses: actions/checkout@v2 12 | - name: Install libmagic-dev 13 | run: sudo apt-get update && sudo apt-get install -y libmagic-dev 14 | - name: Setup ruby 15 | uses: ruby/setup-ruby@v1 16 | with: 17 | bundler-cache: true 18 | - name: Run RuboCop 19 | run: bundle exec rubocop --format github --parallel 20 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | inherit_mode: 4 | merge: 5 | - Exclude 6 | 7 | require: 8 | - rubocop-rails 9 | - rubocop-rspec 10 | - rubocop-rspec_rails 11 | - rubocop-capybara 12 | - rubocop-factory_bot 13 | 14 | AllCops: 15 | NewCops: enable 16 | Exclude: 17 | - 'db/**/*' 18 | - 'bin/*' 19 | 20 | Gemspec/OrderedDependencies: 21 | Exclude: 22 | - 'plugins/*/*.gemspec' 23 | 24 | Metrics/BlockLength: 25 | Exclude: 26 | - 'lib/tasks/foodsoft.rake' 27 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.6 2 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | -o doc/api --no-private --protected app/**/*.rb lib/**/*.rb - *.md doc/**/*.md 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec rails server --binding=0.0.0.0 --port=$PORT 2 | worker: QUEUE=* bundle exec rake resque:work 3 | mail: bundle exec rake foodsoft:reply_email_smtp_server 4 | cron: supercronic crontab 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | # Add your own tasks in files placed in lib/tasks ending in .rake, 3 | 4 | require File.expand_path('config/application', __dir__) 5 | require 'rake' 6 | require 'rspec-rerun/tasks' if defined?(RSpec) # http://stackoverflow.com/a/16853615/2866660 7 | 8 | Foodsoft::Application.load_tasks 9 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 4.9.1 2 | -------------------------------------------------------------------------------- /app/assets/images/b_browse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/b_browse.png -------------------------------------------------------------------------------- /app/assets/images/b_drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/b_drop.png -------------------------------------------------------------------------------- /app/assets/images/b_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/b_edit.png -------------------------------------------------------------------------------- /app/assets/images/b_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/b_user.png -------------------------------------------------------------------------------- /app/assets/images/b_users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/b_users.png -------------------------------------------------------------------------------- /app/assets/images/dots-white.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/dots-white.gif -------------------------------------------------------------------------------- /app/assets/images/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/error.png -------------------------------------------------------------------------------- /app/assets/images/euro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/euro.png -------------------------------------------------------------------------------- /app/assets/images/euro_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/euro_new.png -------------------------------------------------------------------------------- /app/assets/images/icon_message.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/icon_message.gif -------------------------------------------------------------------------------- /app/assets/images/lamp_grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/lamp_grey.png -------------------------------------------------------------------------------- /app/assets/images/lamp_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/lamp_red.png -------------------------------------------------------------------------------- /app/assets/images/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/loader.gif -------------------------------------------------------------------------------- /app/assets/images/package-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/package-bg.png -------------------------------------------------------------------------------- /app/assets/images/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/package.png -------------------------------------------------------------------------------- /app/assets/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/rails.png -------------------------------------------------------------------------------- /app/assets/images/redbox_spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/redbox_spinner.gif -------------------------------------------------------------------------------- /app/assets/images/role-admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-admin.png -------------------------------------------------------------------------------- /app/assets/images/role-article_meta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-article_meta.png -------------------------------------------------------------------------------- /app/assets/images/role-finance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-finance.png -------------------------------------------------------------------------------- /app/assets/images/role-invoices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-invoices.png -------------------------------------------------------------------------------- /app/assets/images/role-orders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-orders.png -------------------------------------------------------------------------------- /app/assets/images/role-pickups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-pickups.png -------------------------------------------------------------------------------- /app/assets/images/role-suppliers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/role-suppliers.png -------------------------------------------------------------------------------- /app/assets/images/save_pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/save_pdf.png -------------------------------------------------------------------------------- /app/assets/images/text_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/images/text_file.png -------------------------------------------------------------------------------- /app/assets/javascripts/bootstrap.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $("a[rel~=popover], .has-popover").popover() 3 | $("a[rel~=tooltip], .has-tooltip").tooltip() 4 | }); 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/app/assets/stylesheets/.gitkeep -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | // "bootstrap-sprockets" must be imported before "bootstrap" and "bootstrap/variables" 2 | @import "bootstrap-sprockets"; 3 | @import "bootstrap"; 4 | @import "font-awesome"; 5 | @import "bootstrap_and_overrides"; 6 | @import "select2"; 7 | @import "select2-bootstrap"; 8 | @import "token-input-bootstrappy"; 9 | @import "bootstrap-datepicker3"; 10 | @import "list.unlist"; 11 | @import "list.missing"; 12 | @import "recurring_select"; 13 | @import "actiontext"; 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/group_order.scss: -------------------------------------------------------------------------------- 1 | .group-order-input { 2 | .btn-group .btn-ordering { 3 | margin-top: 0; 4 | } 5 | 6 | input.goa-quantity, input.goa-tolerance { 7 | height: 24px; 8 | -moz-appearance: textfield; 9 | border-top-right-radius: 0; 10 | border-bottom-right-radius: 0; 11 | &::-webkit-inner-spin-button { 12 | -webkit-appearance: none; 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/assets/stylesheets/ie_hacks.css: -------------------------------------------------------------------------------- 1 | #nav { 2 | text-align: left; } 3 | #nav ul { 4 | margin: 0; } 5 | #nav ul li.current a:hover { 6 | color: white; } 7 | #nav ul li.current ul { 8 | width: 100%; } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/list.missing.css: -------------------------------------------------------------------------------- 1 | .list .missing-many td, .list .missing-many:hover td { 2 | background-color: #ebbebe; 3 | } 4 | 5 | .list .missing-few td, .list .missing-few:hover td { 6 | background-color: #ffee75; 7 | } 8 | 9 | .list .missing-none td, .list .missing-none:hover td { 10 | background-color: #E4EED6; 11 | } 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/list.unlist.css: -------------------------------------------------------------------------------- 1 | .list .unlisted:not(.no-unlist) { 2 | display: none; 3 | } -------------------------------------------------------------------------------- /app/controllers/admin/base_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::BaseController < ApplicationController 2 | before_action :authenticate_admin 3 | 4 | def index 5 | @user = current_user 6 | @groups = Group.where(deleted_at: nil).order('created_on DESC').limit(10) 7 | @users = User.order('created_on DESC').limit(10) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/api/v1/article_categories_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::V1::ArticleCategoriesController < Api::V1::BaseController 2 | include Concerns::CollectionScope 3 | 4 | def index 5 | render json: search_scope 6 | end 7 | 8 | def show 9 | render json: scope.find(params.require(:id)) 10 | end 11 | 12 | private 13 | 14 | def max_per_page 15 | nil 16 | end 17 | 18 | def default_per_page 19 | nil 20 | end 21 | 22 | def scope 23 | ArticleCategory.all 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/controllers/api/v1/configs_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::V1::ConfigsController < Api::V1::BaseController 2 | before_action -> { doorkeeper_authorize! 'config:user', 'config:read', 'config:write' } 3 | 4 | def show 5 | render json: FoodsoftConfig, serializer: ConfigSerializer, root: 'config' 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/api/v1/financial_transaction_classes_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::V1::FinancialTransactionClassesController < Api::V1::BaseController 2 | include Concerns::CollectionScope 3 | 4 | def index 5 | render json: search_scope 6 | end 7 | 8 | def show 9 | render json: scope.find(params.require(:id)) 10 | end 11 | 12 | private 13 | 14 | def max_per_page 15 | nil 16 | end 17 | 18 | def default_per_page 19 | nil 20 | end 21 | 22 | def scope 23 | FinancialTransactionClass.all 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/controllers/api/v1/orders_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::V1::OrdersController < Api::V1::BaseController 2 | include Concerns::CollectionScope 3 | 4 | before_action -> { doorkeeper_authorize! 'orders:read', 'orders:write' } 5 | 6 | def index 7 | render_collection search_scope 8 | end 9 | 10 | def show 11 | render json: scope.find(params.require(:id)) 12 | end 13 | 14 | private 15 | 16 | def scope 17 | Order.includes(:supplier) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/controllers/api/v1/user/users_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::V1::User::UsersController < Api::V1::BaseController 2 | before_action -> { doorkeeper_authorize! 'user:read', 'user:write' } 3 | 4 | def show 5 | render json: current_user 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/concerns/send_order_pdf.rb: -------------------------------------------------------------------------------- 1 | module Concerns::SendOrderPdf 2 | extend ActiveSupport::Concern 3 | 4 | protected 5 | 6 | def send_order_pdf(order, document) 7 | klass = case document 8 | when 'groups' then OrderByGroups 9 | when 'articles' then OrderByArticles 10 | when 'fax' then OrderFax 11 | when 'matrix' then OrderMatrix 12 | end 13 | pdf = klass.new order 14 | send_data pdf.to_pdf, filename: pdf.filename, type: 'application/pdf' 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/controllers/errors_controller.rb: -------------------------------------------------------------------------------- 1 | class ErrorsController < ApplicationController 2 | include Gaffe::Errors 3 | 4 | skip_before_action :authenticate 5 | 6 | layout :current_layout 7 | 8 | def show 9 | render "errors/#{@rescue_response}", formats: :html, status: @status_code 10 | end 11 | 12 | private 13 | 14 | def current_layout 15 | current_user ? 'application' : 'login' 16 | end 17 | 18 | def login_layout? 19 | current_user.nil? 20 | end 21 | helper_method :login_layout? 22 | end 23 | -------------------------------------------------------------------------------- /app/controllers/finance/base_controller.rb: -------------------------------------------------------------------------------- 1 | class Finance::BaseController < ApplicationController 2 | before_action :authenticate_finance 3 | 4 | def index 5 | @financial_transactions = FinancialTransaction.with_ordergroup.includes(:ordergroup).order(created_on: :desc).limit(8) 6 | @orders = Order.finished_not_closed.includes(:supplier).limit(8) 7 | @unpaid_invoices = Invoice.unpaid.includes(:supplier).limit(8) 8 | 9 | render template: 'finance/index' 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/order_comments_controller.rb: -------------------------------------------------------------------------------- 1 | class OrderCommentsController < ApplicationController 2 | def new 3 | @order = Order.find(params[:order_id]) 4 | @order_comment = @order.comments.build(user: current_user) 5 | end 6 | 7 | def create 8 | @order_comment = OrderComment.new(params[:order_comment]) 9 | if @order_comment.save 10 | render layout: false 11 | else 12 | render action: :new, layout: false 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/supplier_shares_controller.rb: -------------------------------------------------------------------------------- 1 | class SupplierSharesController < ApplicationController 2 | before_action :authenticate_suppliers 3 | 4 | def create 5 | @supplier = Supplier.find(params[:supplier_id]) 6 | @supplier.update_attribute(:external_uuid, SecureRandom.uuid) 7 | 8 | render 'update' 9 | end 10 | 11 | def destroy 12 | @supplier = Supplier.find(params[:supplier_id]) 13 | @supplier.update_attribute(:external_uuid, nil) 14 | 15 | render 'update' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | # Currently used to display users nick and ids for autocomplete 3 | def index 4 | @users = User.undeleted.natural_search(params[:q]) 5 | respond_to do |format| 6 | format.json { render json: @users.map(&:token_attributes).to_json } 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/helpers/admin/ordergroups_helper.rb: -------------------------------------------------------------------------------- 1 | module Admin::OrdergroupsHelper 2 | def ordergroup_members_title(ordergroup) 3 | s = '' 4 | s += ordergroup.users.map(&:name).join(', ') if ordergroup.users.any? 5 | s += "\n" + Ordergroup.human_attribute_name(:contact) + ': ' + ordergroup.contact_person if ordergroup.contact_person.present? 6 | s 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/helpers/article_categories_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticleCategoriesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/finance/balancing_helper.rb: -------------------------------------------------------------------------------- 1 | module Finance::BalancingHelper 2 | def balancing_view_partial 3 | view = params[:view] || 'edit_results' 4 | case view 5 | when 'edit_results' 6 | 'edit_results_by_articles' 7 | when 'groups_overview' 8 | 'shared/articles_by/groups' 9 | when 'articles_overview' 10 | 'shared/articles_by/articles' 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/helpers/finance/invoices_helper.rb: -------------------------------------------------------------------------------- 1 | module Finance::InvoicesHelper 2 | def format_delivery_item(delivery) 3 | format_date(delivery.date) 4 | end 5 | 6 | def format_order_item(order) 7 | "#{format_date(order.ends)} (#{number_to_currency(order.sum)})" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/helpers/finance/ordergroups_helper.rb: -------------------------------------------------------------------------------- 1 | module Finance::OrdergroupsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/foodcoop_helper.rb: -------------------------------------------------------------------------------- 1 | module FoodcoopHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/home_helper.rb: -------------------------------------------------------------------------------- 1 | module HomeHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/order_articles_helper.rb: -------------------------------------------------------------------------------- 1 | module OrderArticlesHelper 2 | def article_label_with_unit(article) 3 | pkg_info = pkg_helper(article, plain: true) 4 | "#{article.name} (#{[article.unit, pkg_info].compact_blank.join(' ')})" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/order_comments_helper.rb: -------------------------------------------------------------------------------- 1 | module OrderCommentsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/path_helper.rb: -------------------------------------------------------------------------------- 1 | module PathHelper 2 | def finance_group_transactions_path(ordergroup) 3 | if ordergroup 4 | finance_ordergroup_transactions_path(ordergroup) 5 | else 6 | finance_foodcoop_financial_transactions_path 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/helpers/sessions_helper.rb: -------------------------------------------------------------------------------- 1 | module SessionsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/shared_helper.rb: -------------------------------------------------------------------------------- 1 | module SharedHelper 2 | # provide input_html for password autocompletion 3 | def autocomplete_flag_to_password_html(password_autocomplete) 4 | case password_autocomplete 5 | when true then { autocomplete: 'on' } 6 | when false then { autocomplete: 'off' } 7 | when 'store-only' then { autocomplete: 'off', data: { store: 'on' } } 8 | else {} 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/helpers/stock_takings_helper.rb: -------------------------------------------------------------------------------- 1 | module StockTakingsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/suppliers_helper.rb: -------------------------------------------------------------------------------- 1 | module SuppliersHelper 2 | def shared_sync_method_collection 3 | # TODO: See if we really need the import limit `shared_supplier_article_sync_limit` 4 | # also see https://github.com/foodcoops/foodsoft/pull/609/files and https://github.com/foodcoopsat/foodsoft_hackathon/issues/89 5 | Supplier.shared_sync_methods.keys.map do |m| 6 | [t("suppliers.shared_supplier_methods.#{m}"), m] 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/helpers/users_helper.rb: -------------------------------------------------------------------------------- 1 | module UsersHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/inputs/date_picker_input.rb: -------------------------------------------------------------------------------- 1 | class DatePickerInput < SimpleForm::Inputs::StringInput 2 | def input(wrapper_options) 3 | options = merge_wrapper_options(input_html_options, wrapper_options) 4 | @builder.text_field attribute_name, options.merge(class: 'form-control datepicker') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails 2 | import "trix" 3 | import "@rails/actiontext" 4 | import "trix-editor-overrides" 5 | -------------------------------------------------------------------------------- /app/javascript/trix-editor-overrides.js: -------------------------------------------------------------------------------- 1 | // app/javascript/trix-editor-overrides.js 2 | window.addEventListener("trix-file-accept", function(event) { 3 | if (event.file.size > 1024 * 1024 * 512) { 4 | event.preventDefault() 5 | alert(I18n.t('js.trix_editor.file_size_alert')) 6 | } 7 | }) -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/jobs/notify_finished_order_job.rb: -------------------------------------------------------------------------------- 1 | class NotifyFinishedOrderJob < ApplicationJob 2 | def perform(order) 3 | order.group_orders.each do |group_order| 4 | next unless group_order.ordergroup 5 | 6 | group_order.ordergroup.users.each do |user| 7 | next unless user.settings.notify['order_finished'] 8 | 9 | Mailer.deliver_now_with_user_locale user do 10 | Mailer.order_result(user, group_order) 11 | end 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/jobs/notify_negative_balance_job.rb: -------------------------------------------------------------------------------- 1 | class NotifyNegativeBalanceJob < ApplicationJob 2 | def perform(ordergroup, transaction) 3 | ordergroup.users.each do |user| 4 | next unless user.settings.notify['negative_balance'] 5 | 6 | Mailer.deliver_now_with_user_locale user do 7 | Mailer.negative_balance(user, transaction) 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/jobs/notify_received_order_job.rb: -------------------------------------------------------------------------------- 1 | class NotifyReceivedOrderJob < ApplicationJob 2 | def perform(order) 3 | order.group_orders.each do |group_order| 4 | next unless group_order.ordergroup 5 | 6 | group_order.ordergroup.users.each do |user| 7 | next unless user.settings.notify['order_received'] 8 | 9 | Mailer.deliver_now_with_user_locale user do 10 | Mailer.order_received(user, group_order) 11 | end 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /app/models/article_unit_ratio.rb: -------------------------------------------------------------------------------- 1 | class ArticleUnitRatio < ApplicationRecord 2 | belongs_to :article_version 3 | 4 | default_scope { order(sort: :asc) } 5 | 6 | validates :quantity, :sort, :unit, presence: true 7 | validates :quantity, numericality: { greater_than: 0, less_than: 10**35 } 8 | end 9 | -------------------------------------------------------------------------------- /app/models/assignment.rb: -------------------------------------------------------------------------------- 1 | class Assignment < ApplicationRecord 2 | belongs_to :user 3 | belongs_to :task 4 | end 5 | -------------------------------------------------------------------------------- /app/models/bank_gateway.rb: -------------------------------------------------------------------------------- 1 | class BankGateway < ApplicationRecord 2 | has_many :bank_accounts, dependent: :nullify 3 | belongs_to :unattended_user, class_name: 'User', optional: true 4 | 5 | scope :with_unattended_support, -> { where.not(unattended_user: nil) } 6 | 7 | validates :name, :url, presence: true 8 | end 9 | -------------------------------------------------------------------------------- /app/models/concerns/custom_fields.rb: -------------------------------------------------------------------------------- 1 | module CustomFields 2 | extend ActiveSupport::Concern 3 | include RailsSettings::Extend 4 | 5 | attr_accessor :custom_fields 6 | 7 | included do 8 | after_initialize do 9 | settings.defaults['custom_fields'] = {} unless settings.custom_fields 10 | end 11 | 12 | after_save do 13 | settings.custom_fields = custom_fields if custom_fields 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/models/group_order_article_quantity.rb: -------------------------------------------------------------------------------- 1 | # stores the quantity, tolerance and timestamp of an GroupOrderArticle 2 | # Considers every update of an article-order, so may rows for one group_order_article ar possible. 3 | 4 | class GroupOrderArticleQuantity < ApplicationRecord 5 | belongs_to :group_order_article 6 | 7 | validates :group_order_article_id, presence: true 8 | end 9 | -------------------------------------------------------------------------------- /app/models/mail_delivery_status.rb: -------------------------------------------------------------------------------- 1 | class MailDeliveryStatus < ApplicationRecord 2 | self.table_name = 'mail_delivery_status' 3 | 4 | belongs_to :user, foreign_key: 'email', primary_key: 'email' 5 | end 6 | -------------------------------------------------------------------------------- /app/models/membership.rb: -------------------------------------------------------------------------------- 1 | class Membership < ApplicationRecord 2 | belongs_to :user 3 | belongs_to :group 4 | 5 | before_destroy :check_last_admin 6 | 7 | protected 8 | 9 | # check if this is the last admin-membership and deny 10 | def check_last_admin 11 | raise I18n.t('model.membership.no_admin_delete') if group.role_admin? && group.memberships.size == 1 && Group.where(role_admin: true).count == 1 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/order_comment.rb: -------------------------------------------------------------------------------- 1 | class OrderComment < ApplicationRecord 2 | belongs_to :order 3 | belongs_to :user 4 | 5 | validates :order_id, :user_id, :text, presence: true 6 | validates :text, length: { minimum: 3 } 7 | end 8 | -------------------------------------------------------------------------------- /app/models/stock_event.rb: -------------------------------------------------------------------------------- 1 | class StockEvent < ApplicationRecord 2 | has_many :stock_changes, dependent: :destroy 3 | has_many :stock_articles, through: :stock_changes 4 | 5 | validates :date, presence: true 6 | end 7 | -------------------------------------------------------------------------------- /app/models/stock_taking.rb: -------------------------------------------------------------------------------- 1 | class StockTaking < StockEvent 2 | def stock_change_attributes=(stock_change_attributes) 3 | for attributes in stock_change_attributes 4 | stock_changes.build(attributes) unless attributes[:quantity].to_i == 0 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/serializers/article_category_serializer.rb: -------------------------------------------------------------------------------- 1 | class ArticleCategorySerializer < ActiveModel::Serializer 2 | attributes :id, :name 3 | end 4 | -------------------------------------------------------------------------------- /app/serializers/article_serializer.rb: -------------------------------------------------------------------------------- 1 | class ArticleSerializer < ActiveModel::Serializer 2 | attributes :id, :name 3 | attributes :supplier_id, :supplier_name 4 | attributes :unit, :unit_quantity, :note, :manufacturer, :origin, :article_category_id 5 | 6 | def supplier_name 7 | object.supplier.try(:name) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/serializers/article_unit_serializer.rb: -------------------------------------------------------------------------------- 1 | class ArticleUnitSerializer < ActiveModel::Serializer 2 | attributes :id, :unit 3 | end 4 | -------------------------------------------------------------------------------- /app/serializers/financial_transaction_class_serializer.rb: -------------------------------------------------------------------------------- 1 | class FinancialTransactionClassSerializer < ActiveModel::Serializer 2 | attributes :id, :name 3 | end 4 | -------------------------------------------------------------------------------- /app/serializers/financial_transaction_serializer.rb: -------------------------------------------------------------------------------- 1 | class FinancialTransactionSerializer < ActiveModel::Serializer 2 | include ApplicationHelper 3 | 4 | attributes :id, :user_id, :user_name, :amount, :note, :created_at 5 | attributes :financial_transaction_type_id, :financial_transaction_type_name 6 | 7 | def user_name 8 | show_user object.user 9 | end 10 | 11 | def financial_transaction_type_name 12 | object.financial_transaction_type.name 13 | end 14 | 15 | def amount 16 | object.amount.to_f 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/serializers/group_order_article_serializer.rb: -------------------------------------------------------------------------------- 1 | class GroupOrderArticleSerializer < ActiveModel::Serializer 2 | attributes :id, :order_article_id 3 | attributes :quantity, :tolerance, :result, :total_price 4 | 5 | def total_price 6 | object.total_price.to_f 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/serializers/order_article_serializer.rb: -------------------------------------------------------------------------------- 1 | class OrderArticleSerializer < ActiveModel::Serializer 2 | attributes :id, :order_id, :price 3 | attributes :quantity, :tolerance, :units_to_order 4 | 5 | has_one :article_version 6 | 7 | def price 8 | object.article_version.fc_price.to_f 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/serializers/order_serializer.rb: -------------------------------------------------------------------------------- 1 | class OrderSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :starts, :ends, :boxfill, :pickup, :is_open, :is_boxfill 3 | 4 | def is_open 5 | object.open? 6 | end 7 | 8 | def is_boxfill 9 | object.boxfill? 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/serializers/stock_article_serializer.rb: -------------------------------------------------------------------------------- 1 | class StockArticleSerializer < ArticleSerializer 2 | attribute :quantity_available 3 | 4 | def quantity_available 5 | object.quantity 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/serializers/user_serializer.rb: -------------------------------------------------------------------------------- 1 | class UserSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :email, :locale 3 | end 4 | -------------------------------------------------------------------------------- /app/views/active_storage/blobs/_blob.html.haml: -------------------------------------------------------------------------------- 1 | %figure{class: "attachment attachment--#{blob.representable? ? "preview" : "file"} attachment--#{blob.filename.extension}"} 2 | - if blob.representable? 3 | = image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) 4 | %figcaption.attachment__caption 5 | - if caption = blob.try(:caption) 6 | = caption 7 | - else 8 | %span.attachment__name= link_to blob.filename, blob 9 | %span.attachment__size= number_to_human_size blob.byte_size 10 | -------------------------------------------------------------------------------- /app/views/admin/bank_accounts/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/admin/bank_gateways/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/admin/configs/_tab_messages.html.haml: -------------------------------------------------------------------------------- 1 | .col-md-4 2 | %fieldset 3 | %label 4 | %h4= t '.emails_title' 5 | = config_input form, :email_from, as: :string, input_html: {class: 'form-control', placeholder: "#{@cfg[:name]} <#{@cfg[:contact][:email]}>"} 6 | = config_input form, :email_replyto, as: :string, input_html: {class: 'form-control'} 7 | -# sender is better configured by server administrator, since it affects SPF records 8 | -#= config_input form, :email_sender, as: :string, input_html: {class: 'form-control'} 9 | -------------------------------------------------------------------------------- /app/views/admin/configs/_tab_security.html.haml: -------------------------------------------------------------------------------- 1 | .col-md-4 2 | %h4= t '.default_roles_title' 3 | = t '.default_roles_paragraph' 4 | = config_input form, :default_role_suppliers, as: :boolean 5 | = config_input form, :default_role_article_meta, as: :boolean 6 | = config_input form, :default_role_orders, as: :boolean 7 | = config_input form, :default_role_pickups, as: :boolean 8 | = config_input form, :default_role_finance, as: :boolean 9 | = config_input form, :default_role_invoices, as: :boolean 10 | -------------------------------------------------------------------------------- /app/views/admin/configs/list.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title'), false 2 | 3 | = render 'tabs' 4 | 5 | %table.table 6 | %thead 7 | %tr 8 | %th= t '.key' 9 | %th= t '.value' 10 | %tbody 11 | - @keys.each do |key| 12 | %tr 13 | %td 14 | %tt= key 15 | %td{style: if @cfg[key] != @dfl[key] then 'font-weight: bold' end} 16 | = show_config_value key, @cfg[key] 17 | -------------------------------------------------------------------------------- /app/views/admin/configs/show.html.haml: -------------------------------------------------------------------------------- 1 | - title t('admin.configs.tabs.title'), false 2 | 3 | -# disable validations, because browsers can't handle inputs hidden in another tab 4 | = simple_form_for :config, method: :patch, html: {novalidate: true} do |f| 5 | 6 | = render 'tabs', url: nil 7 | 8 | .tab-content.row.pt-5.pl-5 9 | - for tab in @tabs 10 | .tab-pane{class: ('active' if @current_tab==tab), id: "tab-#{tab}"}= render "tab_#{tab}", form: f 11 | 12 | .col-md-8.pull-right 13 | = f.submit t('.submit'), class: 'btn btn-primary ' 14 | 15 | -------------------------------------------------------------------------------- /app/views/admin/finances/_form.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for [:admin, @financial_transaction_class] do |f| 2 | = f.input :name 3 | .form-group 4 | = f.button :submit 5 | = link_to t('ui.or_cancel'), :back 6 | -------------------------------------------------------------------------------- /app/views/admin/finances/update_bank_accounts.js.haml: -------------------------------------------------------------------------------- 1 | $('#bank_accounts_table').html('#{escape_javascript(render("admin/finances/bank_accounts"))}'); 2 | $('#modalContainer').modal('hide'); 3 | -------------------------------------------------------------------------------- /app/views/admin/finances/update_bank_gateways.js.haml: -------------------------------------------------------------------------------- 1 | $('#bank_gateways_table').html('#{escape_javascript(render("admin/finances/bank_gateways"))}'); 2 | $('#modalContainer').modal('hide'); 3 | -------------------------------------------------------------------------------- /app/views/admin/finances/update_supplier_categories.js.haml: -------------------------------------------------------------------------------- 1 | $('#supplier_categories_table').html('#{escape_javascript(render("admin/finances/supplier_categories"))}'); 2 | $('#modalContainer').modal('hide'); 3 | -------------------------------------------------------------------------------- /app/views/admin/finances/update_transaction_types.js.haml: -------------------------------------------------------------------------------- 1 | $('#transaction_types_table').html('#{escape_javascript(render("admin/finances/transaction_types"))}'); 2 | $('#modalContainer').modal('hide'); 3 | -------------------------------------------------------------------------------- /app/views/admin/financial_transaction_classes/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/admin/financial_transaction_types/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/admin/mail_delivery_status/index.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | - content_for :actionbar do 4 | = link_to t('.destroy_all'), admin_mail_delivery_status_index_path, :method => :delete, class: 'btn btn-danger' 5 | 6 | #maildeliverystatus 7 | = render "maildeliverystatus" 8 | -------------------------------------------------------------------------------- /app/views/admin/mail_delivery_status/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#maildeliverystatus').html('#{escape_javascript(render("maildeliverystatus"))}'); 2 | -------------------------------------------------------------------------------- /app/views/admin/ordergroups/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/admin/ordergroups/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#ordergroups').html('#{escape_javascript(render("ordergroups"))}'); 2 | -------------------------------------------------------------------------------- /app/views/admin/ordergroups/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/admin/ordergroups/show.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title', name: @ordergroup.name 2 | 3 | %section= render 'shared/group', group: @ordergroup 4 | = link_to t('ui.edit'), edit_admin_ordergroup_path(@ordergroup), class: 'btn btn-default' 5 | = link_to t('ui.delete'), [:admin, @ordergroup], :data => {:confirm => t('.confirm')}, :method => :delete, class: 'btn btn-danger' 6 | -------------------------------------------------------------------------------- /app/views/admin/supplier_categories/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/admin/users/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' 4 | -------------------------------------------------------------------------------- /app/views/admin/users/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#users').html('#{escape_javascript(render("users"))}'); 2 | -------------------------------------------------------------------------------- /app/views/admin/users/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/admin/workgroups/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/admin/workgroups/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#workgroups').html('#{escape_javascript(render("workgroups"))}'); 2 | -------------------------------------------------------------------------------- /app/views/admin/workgroups/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title' 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/admin/workgroups/show.html.haml: -------------------------------------------------------------------------------- 1 | - title t '.title', name: @workgroup.name 2 | 3 | %section= render 'shared/group', group: @workgroup 4 | = link_to t('ui.edit'), edit_admin_workgroup_path(@workgroup), class: 'btn btn-default' 5 | = link_to t('ui.delete'), [:admin, @workgroup], :data => {:confirm => t('.confirm')}, :method => :delete, class: 'btn btn-danger' 6 | -------------------------------------------------------------------------------- /app/views/article_categories/_form.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for @article_category do |f| 2 | = f.input :name 3 | = f.input :description, as: :text, input_html: {class: 'form-control'} 4 | %div 5 | = f.button :submit 6 | = link_to t('ui.or_cancel'), article_categories_path 7 | -------------------------------------------------------------------------------- /app/views/article_categories/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | = render 'form' 4 | -------------------------------------------------------------------------------- /app/views/article_categories/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | = render 'form' 4 | -------------------------------------------------------------------------------- /app/views/article_units/_create_link.html.haml: -------------------------------------------------------------------------------- 1 | = link_to t('.add'), article_units_path(unit: unit), class: 'btn default btn-xs', remote: true, method: :post, data: {'for-unit': unit, 'e2e-create-unit': unit} 2 | -------------------------------------------------------------------------------- /app/views/article_units/_destroy_link.html.haml: -------------------------------------------------------------------------------- 1 | =link_to t('.delete'), article_unit, method: :delete, class: 'btn btn-xs btn-danger', remote: true, data: { confirm: t('.confirm'), 'for-unit': article_unit.unit, 'e2e-destroy-unit': article_unit.unit } 2 | -------------------------------------------------------------------------------- /app/views/article_units/create.js.haml: -------------------------------------------------------------------------------- 1 | $('#main').prepend('#{j(render(:partial => 'shared/alert_success', :locals => {:alert_message => t('.success', name: @available_units[@article_unit.unit][:name])}))}') 2 | $('a[data-for-unit="#{@article_unit.unit}"]').replaceWith('#{j(render(partial: "destroy_link", locals: {article_unit: @article_unit}))}') 3 | -------------------------------------------------------------------------------- /app/views/article_units/destroy.js.haml: -------------------------------------------------------------------------------- 1 | $('#main').prepend('#{j(render(:partial => 'shared/alert_success', :locals => {:alert_message => t('.success', name: @available_units[@article_unit.unit][:name])}))}') 2 | $('a[data-for-unit="#{@article_unit.unit}"]').replaceWith('#{j(render(partial: "create_link", locals: {unit: @article_unit.unit}))}') 3 | -------------------------------------------------------------------------------- /app/views/article_units/search.js.haml: -------------------------------------------------------------------------------- 1 | $('#article_units_search_results').html('#{j(render("rows"))}'); 2 | -------------------------------------------------------------------------------- /app/views/articles/_destroy_active_article.html.haml: -------------------------------------------------------------------------------- 1 | %tr.edit_inline{:id=> "edit_"+@article.id.to_s} 2 | %td{:colspan=>"10"} 3 | = t('.note', article: h(@article.name), drop_link: link_to(t('.drop'), edit_order_path(@order))).html_safe 4 | -------------------------------------------------------------------------------- /app/views/articles/copy.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/articles/create.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').modal('hide'); 2 | $('#listbody').prepend('#{escape_javascript(render(@article))}'); 3 | const importActionsCell$ = $('#import #search_results td[data-order-number="#{escape_javascript(@article.order_number)}"]'); 4 | importActionsCell$.find('.icon-ok').show(); 5 | importActionsCell$.find('.article_import_btn').hide(); 6 | = render 'import_article_added', article: @article if @article.shared_article 7 | -------------------------------------------------------------------------------- /app/views/articles/destroy.js.haml: -------------------------------------------------------------------------------- 1 | - if @order 2 | $('#article_#{@article.id}').after('#{escape_javascript(render("destroy_active_article"))}'); 3 | - else 4 | $('#article_#{@article.id}').remove(); 5 | const importActionsCell$ = $('#import #search_results td[data-order-number="#{escape_javascript(@article.order_number)}"]'); 6 | importActionsCell$.find('.icon-ok').hide(); 7 | importActionsCell$.find('.article_import_btn').show(); 8 | -------------------------------------------------------------------------------- /app/views/articles/edit.html.haml: -------------------------------------------------------------------------------- 1 | 2 | =render("form") -------------------------------------------------------------------------------- /app/views/articles/edit_all.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', supplier: @supplier.name) 2 | %p 3 | %i= t '.note' 4 | = form_tag(update_all_supplier_articles_path(@supplier)) do 5 | = render 'edit_all_table' 6 | = hidden_field_tag :complete_migration, true unless @original_units.nil? 7 | %br/ 8 | %i= t '.warning' 9 | %div 10 | = submit_tag t('.submit'), class: 'btn btn-primary', disabled: true 11 | = link_to t('ui.or_cancel'), supplier_articles_path(@supplier) 12 | -------------------------------------------------------------------------------- /app/views/articles/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#table').html('#{escape_javascript(render("articles"))}'); 2 | -------------------------------------------------------------------------------- /app/views/articles/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').addClass('modal-xl').html('#{j(render("form"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/articles/parse_upload.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', supplier: @supplier.name) 2 | 3 | = form_tag update_synchronized_supplier_articles_path(@supplier) do 4 | = hidden_field_tag :from_action, 'parse_upload' 5 | = hidden_field_tag :enable_unit_migration, @enable_unit_migration ? '1' : '0' 6 | = render 'sync' 7 | %div 8 | = submit_tag t('.submit'), class: 'btn btn-primary' 9 | = link_to t('ui.or_cancel'), upload_supplier_articles_path(@supplier) 10 | -------------------------------------------------------------------------------- /app/views/articles/prepare_units_migration.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', supplier: @supplier.name) 2 | %p.mb-1 3 | =simple_format(t('.explanation')) 4 | = link_to t('.download'), supplier_articles_path(@supplier, format: :csv), class: 'btn' 5 | %br/ 6 | %br/ 7 | %p.mt-1 8 | = link_to t('.migrate_units') + '...', migrate_units_supplier_articles_path(@supplier), class: 'btn btn-success' if @supplier.unit_migration_completed.nil? 9 | -------------------------------------------------------------------------------- /app/views/articles/sync.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | = form_tag update_synchronized_supplier_articles_path(@supplier) do 4 | = hidden_field_tag :from_action, 'sync' 5 | = render 'sync' 6 | %div 7 | = submit_tag t('.submit'), class: 'btn btn-primary' 8 | = link_to t('ui.or_cancel'), supplier_articles_path(@supplier) 9 | -------------------------------------------------------------------------------- /app/views/articles/update.js.haml: -------------------------------------------------------------------------------- 1 | $('#article_#{@article.id}').replaceWith('#{escape_javascript(render(@article))}'); 2 | $('#modalContainer').removeClass('modal-xl').modal('hide'); 3 | -------------------------------------------------------------------------------- /app/views/deliveries/_stock_change.html.haml: -------------------------------------------------------------------------------- 1 | - if stock_change.stock_article.new_record? 2 | = simple_fields_for "delivery[new_stock_changes_new_stock_article][]", stock_change do |f| 3 | = render :partial => 'stock_change_fields', :locals => {:f => f} 4 | - else 5 | = simple_fields_for "delivery[new_stock_changes][]", stock_change do |f| 6 | = render :partial => 'stock_change_fields', :locals => {:f => f} 7 | -------------------------------------------------------------------------------- /app/views/deliveries/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | = render :partial => 'form' 4 | -------------------------------------------------------------------------------- /app/views/deliveries/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', supplier: @supplier.name) 2 | 3 | = render 'form' 4 | -------------------------------------------------------------------------------- /app/views/errors/_error.html.haml: -------------------------------------------------------------------------------- 1 | - title local_assigns[:title], false 2 | 3 | - unless login_layout? 4 | %i.hidden-xs.glyphicon.glyphicon-exclamation-sign 5 | %div(class="#{login_layout? ? '' : 'col-md-6'}") 6 | %h1= local_assigns[:title] 7 | %div(class='alert alert-#{local_assigns[:type] || 'warn'}') 8 | = local_assigns[:page] 9 | = link_to t('ui.back'), 'javascript:history.go(-1)', class: 'btn btn-primary' 10 | -------------------------------------------------------------------------------- /app/views/errors/internal_server_error.html.haml: -------------------------------------------------------------------------------- 1 | - page = capture do 2 | %p= t '.text1' 3 | %p= t '.text2' 4 | 5 | = render 'error', title: t('.title'), type: :error, page: page 6 | -------------------------------------------------------------------------------- /app/views/errors/not_found.html.haml: -------------------------------------------------------------------------------- 1 | - page = capture do 2 | %p= t '.text' 3 | 4 | = render 'error', title: t('.title'), page: page 5 | -------------------------------------------------------------------------------- /app/views/finance/balancing/_edit_note.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for @order, url: update_note_finance_order_path(@order), remote: true, method: :put do |f| 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | = close_button :modal 6 | %h3= t('.title') 7 | .modal-body 8 | = f.input :note, input_html: {class: 'form-control', rows: 10, cols: 80} 9 | .modal-footer 10 | = link_to t('ui.close'), '#', class: 'btn btn-default', data: {dismiss: 'modal'} 11 | = f.submit t('ui.save'), class: 'btn btn-primary' 12 | -------------------------------------------------------------------------------- /app/views/finance/balancing/_order_article_result.html.haml: -------------------------------------------------------------------------------- 1 | %tr[order_article] 2 | = render :partial => 'finance/balancing/order_article', :locals => {:order_article => order_article} 3 | 4 | %tr{:id => "group_order_articles_#{order_article.id}", :class => "results", :style => "display:none"} 5 | = render :partial => 'finance/balancing/group_order_articles', :locals => {:order_article => order_article} -------------------------------------------------------------------------------- /app/views/finance/balancing/edit_note.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("edit_note"))}'); 2 | $('#modalContainer').modal(); -------------------------------------------------------------------------------- /app/views/finance/balancing/edit_transport.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("edit_transport"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/finance/balancing/index.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | - content_for :actionbar do 4 | - if FoodsoftConfig[:charge_members_manually] 5 | = link_to t('.close_all_direct_with_invoice'), close_all_direct_with_invoice_finance_order_index_path, method: :post, class: 'btn' 6 | 7 | #ordersTable= render 'orders' 8 | -------------------------------------------------------------------------------- /app/views/finance/balancing/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#ordersTable').html('#{j(render('orders'))}'); -------------------------------------------------------------------------------- /app/views/finance/balancing/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#results').html('#{j(render(balancing_view_partial, order: @order))}'); 2 | $('*[name="group_order_article[result]"]').each((_, field) => $(field).unitConversionField({units: unitsData, popoverTemplate$: $('#unit_conversion_popover_content_template'), useTargetUnitForStep: false})); 3 | -------------------------------------------------------------------------------- /app/views/finance/balancing/update_note.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').modal('hide'); 2 | $('#note').html('#{j(simple_format(@order.note))}'); 3 | -------------------------------------------------------------------------------- /app/views/finance/balancing/update_summary.js.haml: -------------------------------------------------------------------------------- 1 | $('#summary').html('#{j(render('finance/balancing/summary', order: @order))}'); -------------------------------------------------------------------------------- /app/views/finance/bank_accounts/import.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', name: @bank_account.name) 2 | 3 | #import 4 | = render "import" 5 | -------------------------------------------------------------------------------- /app/views/finance/bank_accounts/import.js.haml: -------------------------------------------------------------------------------- 1 | - if @js_redirect 2 | document.location.replace('#{escape_javascript(@js_redirect)}'); 3 | - else 4 | $('#import').html('#{escape_javascript(render("import"))}'); 5 | -------------------------------------------------------------------------------- /app/views/finance/bank_transactions/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#transactionsTable').html('#{j(render('transactions'))}'); 2 | -------------------------------------------------------------------------------- /app/views/finance/financial_links/incomplete.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | %table.table.table-striped 4 | %thead 5 | %tr 6 | %th= heading_helper FinancialLink, :id 7 | %th= heading_helper FinancialLink, :note 8 | %th= heading_helper FinancialTransaction, :amount 9 | %tbody 10 | - for fl in @financial_links 11 | %tr 12 | %td= link_to fl.id, finance_link_path(fl) 13 | %td= fl.note 14 | %td= format_currency fl.full_sum 15 | -------------------------------------------------------------------------------- /app/views/finance/financial_links/index_bank_transaction.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("index_bank_transaction"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/finance/financial_links/index_financial_transaction.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("index_financial_transaction"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/finance/financial_links/index_invoice.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("index_invoice"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/finance/financial_links/new_financial_transaction.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render("new_financial_transaction"))}'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/finance/financial_transactions/_order_note.html.haml: -------------------------------------------------------------------------------- 1 | - financial_transaction = local_assigns[:financial_transaction] 2 | - with_grouporder_link = local_assigns[:with_grouporder_link] 3 | - if financial_transaction.group_order 4 | - if with_grouporder_link 5 | = link_to financial_transaction.note, financial_transaction.group_order 6 | - else 7 | = link_to financial_transaction.note, new_finance_order_path(order_id: financial_transaction.group_order.order.id) 8 | - else 9 | = financial_transaction.note 10 | -------------------------------------------------------------------------------- /app/views/finance/financial_transactions/_ordergroup.haml: -------------------------------------------------------------------------------- 1 | %tr.transaction 2 | %td 3 | = select_tag 'financial_transactions[][ordergroup_id]', 4 | options_for_select(Ordergroup.undeleted.order(:name).map { |g| [ g.name, g.id ] }), 5 | class: 'form-control' 6 | %td= text_field_tag 'financial_transactions[][amount]', nil, class: 'form-control' 7 | %td= link_to t('.remove'), "#", :title => t('.remove_group'), 'data-remove-transaction' => true, 8 | class: 'btn btn-sm' 9 | -------------------------------------------------------------------------------- /app/views/finance/financial_transactions/index.js.erb: -------------------------------------------------------------------------------- 1 | $('#transactions').html('<%= escape_javascript(render("transactions", with_csv: true, with_hidden: true)) %>'); 2 | -------------------------------------------------------------------------------- /app/views/finance/financial_transactions/index_collection.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | - content_for :actionbar do 4 | = link_to t('.show_groups'), finance_ordergroups_path, class: 'btn btn-default' 5 | 6 | = render 'transactions_search', url: finance_transactions_path 7 | 8 | #transactions= render 'transactions', with_ordergroup: true, with_csv: true 9 | -------------------------------------------------------------------------------- /app/views/finance/financial_transactions/index_collection.js.erb: -------------------------------------------------------------------------------- 1 | $('#transactions').html('<%= escape_javascript(render("transactions", with_ordergroup: true, with_csv: true)) %>'); 2 | -------------------------------------------------------------------------------- /app/views/finance/invoices/_form_js.html.haml: -------------------------------------------------------------------------------- 1 | - content_for :javascript do 2 | :javascript 3 | $(function() { 4 | if ($('#invoice_delivery_ids').length) 5 | $('#invoice_delivery_ids').select2(); 6 | $('#invoice_order_ids').select2(); 7 | $('#invoice_supplier_id').change(function(e) { 8 | $.ajax({ 9 | url: '#{form_on_supplier_id_change_finance_invoices_path}', 10 | type: 'get', 11 | data: {invoice_id: #{invoice_id}, supplier_id: $('#invoice_supplier_id').val()} 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /app/views/finance/invoices/delete_attachment.js.erb: -------------------------------------------------------------------------------- 1 | $("#attachment_<%= params[:attachment_id] %>").remove(); -------------------------------------------------------------------------------- /app/views/finance/invoices/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | = render :partial => 'form', :locals => {:invoice_id => @invoice.id} 3 | -------------------------------------------------------------------------------- /app/views/finance/invoices/index.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | - content_for :actionbar do 4 | = link_to t('.show_unpaid'), unpaid_finance_invoices_path, class: 'btn btn-default' 5 | = link_to t('.action_new'), new_finance_invoice_path, class: 'btn btn-primary' 6 | 7 | #invoicesTable= render 'invoices' 8 | -------------------------------------------------------------------------------- /app/views/finance/invoices/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#invoicesTable').html('#{j(render('invoices'))}'); -------------------------------------------------------------------------------- /app/views/finance/invoices/new.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | = render :partial => 'form', :locals => {:invoice_id => 0} 3 | -------------------------------------------------------------------------------- /app/views/finance/ordergroups/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#ordergroupsTable').html('#{escape_javascript(render("ordergroups"))}'); 2 | -------------------------------------------------------------------------------- /app/views/foodcoop/ordergroups/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#ordergroups').html('#{escape_javascript(render("ordergroups"))}'); 2 | -------------------------------------------------------------------------------- /app/views/foodcoop/users/index.js.haml: -------------------------------------------------------------------------------- 1 | $('#users').html('#{escape_javascript(render("users"))}'); 2 | -------------------------------------------------------------------------------- /app/views/foodcoop/workgroups/_workgroup.html.haml: -------------------------------------------------------------------------------- 1 | %section.well 2 | %h3= workgroup.name 3 | = render :partial => 'shared/group', :locals => { :group => workgroup } 4 | = link_to t('.show_tasks'), workgroup_tasks_path(workgroup_id: workgroup), class: 'btn btn-default' 5 | - if workgroup.member?(current_user) 6 | = link_to t('.edit'), edit_foodcoop_workgroup_path(workgroup), class: 'btn btn-default' 7 | -------------------------------------------------------------------------------- /app/views/foodcoop/workgroups/edit.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | - unless FoodsoftConfig[:disable_invite] 4 | %p= t('.invite_new', invite_link: link_to(t('.invite_link'), new_invite_path(id: @workgroup.id))).html_safe 5 | 6 | .col-md-3 7 | = simple_form_for [:foodcoop, @workgroup] do |f| 8 | = render 'shared/group_form_fields', f: f 9 | .form-group 10 | .col-sm-offset-2.col-sm-10 11 | = f.button :submit 12 | = link_to t('ui.or_cancel'), foodcoop_workgroups_path 13 | -------------------------------------------------------------------------------- /app/views/foodcoop/workgroups/index.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title') 2 | 3 | = t('.body').html_safe 4 | 5 | = render :partial => "workgroup", :collection => @workgroups 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/views/group_order_articles/create.js.erb: -------------------------------------------------------------------------------- 1 | $('#modalContainer').modal('hide'); 2 | 3 | // trigger hooks for views 4 | $(document).trigger({ 5 | type: 'GroupOrderArticle#create', 6 | order_article_id: <%= @group_order_article.order_article_id %>, 7 | group_order_id: <%= @group_order_article.group_order_id %>, 8 | group_order_article_id: <%= @group_order_article.id %>, 9 | group_order_article_price: <%= @group_order_article.total_price %> 10 | }); 11 | -------------------------------------------------------------------------------- /app/views/group_order_articles/new.js.erb: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('<%= j render("form") %>'); 2 | $('#modalContainer').modal(); 3 | -------------------------------------------------------------------------------- /app/views/group_order_articles/update.js.erb: -------------------------------------------------------------------------------- 1 | // and trigger hooks for views including this 2 | $(document).trigger({ 3 | type: 'GroupOrderArticle#update', 4 | order_article_id: <%= @group_order_article.order_article_id %>, 5 | group_order_id: <%= @group_order_article.group_order_id %>, 6 | group_order_article_id: <%= @group_order_article.id %>, 7 | group_order_article_price: <%= @group_order_article.total_price %> 8 | }); 9 | -------------------------------------------------------------------------------- /app/views/group_orders/_switch_order.html.haml: -------------------------------------------------------------------------------- 1 | - orders = Order.open.started.reject{ |order| order == current_order } 2 | - unless orders.empty? 3 | %h2= t '.title' 4 | %ul.list-unstyled 5 | - orders.each do |order| 6 | %li 7 | = link_to_ordering(order, 'data-confirm_switch_order' => true) 8 | - if order.ends 9 | = t '.remaining', remaining: time_ago_in_words(order.ends) 10 | -------------------------------------------------------------------------------- /app/views/group_orders/archive.html.haml: -------------------------------------------------------------------------------- 1 | - title t('.title', group: @ordergroup.name) 2 | %p 3 | = t('.desc', link: link_to(t('.open_orders'), group_orders_path)).html_safe 4 | 5 | .row 6 | .col-md-6 7 | %h2= t '.title_open' 8 | = render partial: 'orders', locals: {orders: @finished_not_closed_orders_including_group_order, pagination: false} 9 | 10 | .col-md-6 11 | %h2= t '.title_closed' 12 | #closed_orders 13 | = render partial: 'orders', locals: {orders: @closed_orders_including_group_order, pagination: true} 14 | -------------------------------------------------------------------------------- /app/views/group_orders/archive.js.haml: -------------------------------------------------------------------------------- 1 | $('#closed_orders').html('#{escape_javascript(render("orders", orders: @closed_orders_including_group_order, pagination: true))}'); 2 | -------------------------------------------------------------------------------- /app/views/group_orders/edit.html.haml: -------------------------------------------------------------------------------- 1 | = render 'form' -------------------------------------------------------------------------------- /app/views/group_orders/new.html.haml: -------------------------------------------------------------------------------- 1 | = render 'form' -------------------------------------------------------------------------------- /app/views/home/_apple_bar.html.haml: -------------------------------------------------------------------------------- 1 | = t '.points', points: apple_bar.apples 2 | .progress 3 | %div{class: "progress-bar progress-bar-#{apple_bar.group_bar_state}", style: "width: #{apple_bar.group_bar_width}%"} 4 | 5 | %span.description 6 | = t '.desc', amount: number_to_currency(apple_bar.mean_order_amount_per_job, :precision=>0) 7 | - if FoodsoftConfig[:stop_ordering_under].present? 8 | %strong= t('.warning', threshold: FoodsoftConfig[:stop_ordering_under]) 9 | = link_to t('.more_info'), FoodsoftConfig[:applepear_url], target: '_blank' 10 | -------------------------------------------------------------------------------- /app/views/home/ordergroup.js.haml: -------------------------------------------------------------------------------- 1 | $('#transactions').html('#{j(render("finance/financial_transactions/transactions"))}'); 2 | -------------------------------------------------------------------------------- /app/views/invites/create.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').modal('hide'); -------------------------------------------------------------------------------- /app/views/invites/new.html.haml: -------------------------------------------------------------------------------- 1 | = t('.body', group: @invite.group.name).html_safe 2 | = simple_form_for @invite do |form| 3 | = form.hidden_field :user_id 4 | = form.hidden_field :group_id 5 | = form.input :email 6 | = form.submit t('.action') 7 | = link_to t('ui.or_cancel'), :back 8 | -------------------------------------------------------------------------------- /app/views/invites/new.js.haml: -------------------------------------------------------------------------------- 1 | $('#modalContainer').html('#{j(render('modal_form'))}'); 2 | $('#modalContainer').modal(); -------------------------------------------------------------------------------- /app/views/kaminari/_first_page.html.haml: -------------------------------------------------------------------------------- 1 | -# 2 | Link to the "First" page 3 | - available local variables 4 | url: url to the first page 5 | current_page: a page object for the currently displayed page 6 | num_pages: total number of pages 7 | per_page: number of items to fetch per page 8 | remote: data-remote 9 | 10 | - unless current_page.first? 11 | %li{:class => "first"} 12 | = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote -------------------------------------------------------------------------------- /app/views/kaminari/_gap.html.haml: -------------------------------------------------------------------------------- 1 | -# 2 | Non-link tag that stands for skipped pages... 3 | - available local variables 4 | current_page: a page object for the currently displayed page 5 | num_pages: total number of pages 6 | per_page: number of items to fetch per page 7 | remote: data-remote 8 | 9 | %li{:class => "page gap disabled"} 10 | %a{:href => "#", :onclick => "return false;"} 11 | = raw(t 'views.pagination.truncate') -------------------------------------------------------------------------------- /app/views/kaminari/_next_page.html.haml: -------------------------------------------------------------------------------- 1 | -# 2 | Link to the "Next" page 3 | - available local variables 4 | url: url to the next page 5 | current_page: a page object for the currently displayed page 6 | num_pages: total number of pages 7 | per_page: number of items to fetch per page 8 | remote: data-remote 9 | 10 | - unless current_page.last? 11 | %li{:class=>"next_page"} 12 | = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote -------------------------------------------------------------------------------- /app/views/kaminari/_page.html.haml: -------------------------------------------------------------------------------- 1 | -# 2 | Link showing page number 3 | - available local variables 4 | page: a page object for "this" page 5 | url: url to this page 6 | current_page: a page object for the currently displayed page 7 | num_pages: total number of pages 8 | per_page: number of items to fetch per page 9 | remote: data-remote 10 | %li{:class=>"page #{' active' if page.current? }"} 11 | = link_to page, url, opts = {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} -------------------------------------------------------------------------------- /app/views/kaminari/_prev_page.html.haml: -------------------------------------------------------------------------------- 1 | -# 2 | Link to the "Previous" page 3 | - available local variables 4 | url: url to the previous page 5 | current_page: a page object for the currently displayed page 6 | num_pages: total number of pages 7 | per_page: number of items to fetch per page 8 | remote: data-remote 9 | 10 | - unless current_page.first? 11 | %li{:class=>"prev"} 12 | = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote -------------------------------------------------------------------------------- /app/views/layouts/action_text/contents/_content.html.erb: -------------------------------------------------------------------------------- 1 |
In ein paar Minuten dürfte aber wieder alles wieder funktionieren.... Nur Geduld ...
10 | 11 | 12 | -------------------------------------------------------------------------------- /public/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /public/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /public/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /public/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /public/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | 3 | # Disallow all robot access: 4 | User-agent: * 5 | Disallow: / -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../config/application', __dir__) 5 | require File.expand_path('../config/boot', __dir__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /spec/factories/article_category.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :article_category do 5 | sequence(:name) { |n| Faker::Lorem.characters(number: rand(2..12)) + " ##{n}" } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/article_unit.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :article_unit do 5 | sequence(:unit) { |n| Faker::Lorem.characters(number: rand(2..12)) + " ##{n}" } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/article_unit_ratio.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :article_unit_ratio do 5 | unit { 'XPP' } 6 | sort { 1 } 7 | quantity { 1 } 8 | article_version 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/factories/bank_transaction_type.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :bank_account do 5 | name { Faker::Bank.name } 6 | iban { Faker::Bank.iban } 7 | end 8 | 9 | factory :bank_transaction do 10 | date { Faker::Date.backward(days: 14) } 11 | text { Faker::Lorem.sentence } 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/delivery.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :delivery do 5 | supplier { create(:supplier) } 6 | date { Time.now } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/doorkeeper.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | require 'doorkeeper' 3 | 4 | FactoryBot.define do 5 | factory :oauth2_application, class: 'Doorkeeper::Application' do 6 | name { Faker::App.name } 7 | redirect_uri { 'https://example.com:1234/app' } 8 | end 9 | 10 | factory :oauth2_access_token, class: 'Doorkeeper::AccessToken' do 11 | application factory: :oauth2_application 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/financial_transaction_type.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :financial_transaction_class do 5 | sequence(:name) { |n| Faker::Lorem.characters(number: rand(2..12)) + " ##{n}" } 6 | end 7 | 8 | factory :financial_transaction_type do 9 | financial_transaction_class 10 | sequence(:name) { |n| Faker::Lorem.words(number: rand(2..4)).join(' ') + " ##{n}" } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/factories/group_order.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | # requires order 5 | factory :group_order do 6 | ordergroup { create(:user, groups: [FactoryBot.create(:ordergroup)]).ordergroup } 7 | updated_by { create(:user) } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/group_order_article.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | # requires order_article 5 | factory :group_order_article do 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/group_order_article_quantity.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | # requires order_article 5 | factory :group_order_article_quantity do 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/invoice.rb: -------------------------------------------------------------------------------- 1 | require 'factory_bot' 2 | 3 | FactoryBot.define do 4 | factory :invoice do 5 | supplier 6 | number { rand(1..99_999) } 7 | amount { rand(0.1..26.0).round(2) } 8 | created_by { create(:user) } 9 | 10 | after :create do |invoice| 11 | invoice.supplier.reload 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/fixtures/foodsoft_file_01.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/spec/fixtures/foodsoft_file_01.ods -------------------------------------------------------------------------------- /spec/fixtures/foodsoft_file_01.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/spec/fixtures/foodsoft_file_01.xls -------------------------------------------------------------------------------- /spec/fixtures/foodsoft_file_01.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/spec/fixtures/foodsoft_file_01.xlsx -------------------------------------------------------------------------------- /spec/fixtures/foodsoft_file_02.csv: -------------------------------------------------------------------------------- 1 | avail.;Order number;Name;Supplier order unit;Unit;Ratios to supplier order unit;Minimum order quantity;Billing unit;Group order granularity;Group order unit;Price (net);Price unit;VAT;Deposit;Note;Category;Origin;Manufacturer 2 | Yes;1;Tomatoes;;500 g;20 Piece;;;1;;1.2;;6;0;organic;Vegetables;Somewhere, UK;Tommy farm 3 | -------------------------------------------------------------------------------- /spec/i18n_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'i18n-spec' 3 | 4 | Dir.glob('config/locales/??{-*,}.yml').each do |locale_file| 5 | describe "#{locale_file}" do 6 | it_behaves_like 'a valid locale file', locale_file 7 | # We're currently allowing both German and English as source language 8 | # besides, we're using localeapp, so that it's ok if pull requests 9 | # don't have this - a localapp pull will fix that right away. 10 | # it { expect(locale_file).to be_a_subset_of 'config/locales/en.yml' } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/requests/api/v1/configs_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'swagger_helper' 2 | 3 | describe Api::V1::ConfigsController do 4 | include ApiHelper 5 | 6 | path '/config' do 7 | get 'configuration variables' do 8 | tags 'General' 9 | produces 'application/json' 10 | let(:api_scopes) { ['config:user'] } 11 | 12 | response '200', 'success' do 13 | schema type: :object, properties: {} 14 | run_test! 15 | end 16 | 17 | it_handles_invalid_token_and_scope 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | # load FactoryBot shortcuts create(), etc. 3 | config.include FactoryBot::Syntax::Methods 4 | end 5 | -------------------------------------------------------------------------------- /spec/support/faker.rb: -------------------------------------------------------------------------------- 1 | module Faker 2 | class Unit 3 | class << self 4 | def unit 5 | %w[kg 1L 100ml piece bunch 500g].sample 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/support/integration.rb: -------------------------------------------------------------------------------- 1 | # @see http://stackoverflow.com/a/11048669/2866660 2 | def scrolldown 3 | page.execute_script 'window.scrollBy(0,10000)' 4 | end 5 | -------------------------------------------------------------------------------- /spec/support/session_helper.rb: -------------------------------------------------------------------------------- 1 | module SessionHelper 2 | def login(user = nil, password = nil) 3 | visit login_path 4 | user = FactoryBot.create(:user) if user.nil? 5 | if user.instance_of? ::User 6 | nick = user.nick 7 | password = user.password 8 | else 9 | nick = user 10 | end 11 | fill_in 'nick', with: nick 12 | fill_in 'password', with: password 13 | find('input[type=submit]').click 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /tmp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /vendor/assets/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/vendor/assets/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /vendor/assets/fonts/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/vendor/assets/fonts/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /vendor/assets/fonts/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/vendor/assets/fonts/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /vendor/assets/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/vendor/assets/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /vendor/javascript/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foodcoops/foodsoft/f9416f2369b3637941f7e4d80bd92044e3bee6cd/vendor/javascript/.keep --------------------------------------------------------------------------------