Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
54fe37b
feat: add initial structure for invoices plugin
Jul 3, 2025
b4d1d3e
feat(invoices): add basic data model
Jul 8, 2025
881ade8
feat(invoices): add basic group order invoice view
Jul 17, 2025
c1e5f4b
feat(assets): introduce dynamic asset registry
Jul 17, 2025
ef36e91
feat(invoices): add dynamic asset registration
Jul 17, 2025
9516209
feat(config): add tax number and invoice settings
Jul 17, 2025
77f0377
feat(invoices): allow to create group order invoices
Jul 17, 2025
c3ad319
feat(invoices): add group order invoice PDF generation
Jul 17, 2025
e20986c
feat(invoices): activate delete link for group order invoices
Jul 24, 2025
ede8cd1
feat(invoices): activate toggle for paid status in group order invoices
Jul 24, 2025
cefd891
feat(invoices): remove SEPA-related functionality
Jul 24, 2025
309bac1
feat(invoices): add bulk creation for group order invoices
Jul 24, 2025
c8ae052
feat(invoices): enable bulk toggle and download for group order invoices
Jul 24, 2025
8d0b16b
feat(locales): add file date format to time formats
Jul 24, 2025
b6951a2
feat(locales): add Dutch translations for group order invoices
Jul 24, 2025
e798e1c
refactor(invoices): fix rubocop offenses
Jul 24, 2025
8a31e97
feat(invoices): add gem and spec for group order invoices
Jul 26, 2025
b5d9f57
fix(migrations): enforce NOT NULL constraint on boolean fields
Jul 29, 2025
6e5fb3a
feat(workflows): add plugin migrations step to Ruby CI
Jul 29, 2025
4d63531
feat(invoices): enhance GroupOrderInvoicePdf generation
Jul 29, 2025
b27b419
refactor(invoices): improve GroupOrderInvoicePdf structure
Jul 29, 2025
e56d66c
docs(invoices): update README with configuration and migration steps
Jul 29, 2025
822bc9c
feat(invoices): update UI for toggling invoice paid status
Jul 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ jobs:
env:
DATABASE_URL: mysql2://user:password@127.0.0.1/test
RAILS_ENV: test
- name: Apply plugin migrations
run: bundle exec rake foodsoft_invoices_engine:install:migrations db:migrate
env:
DATABASE_URL: mysql2://user:password@127.0.0.1/test
RAILS_ENV: test
- name: Run tests
run: bundle exec rake rspec-rerun:spec
env:
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ gem 'foodsoft_wiki', path: 'plugins/wiki'
# gem 'foodsoft_printer', path: 'plugins/printer'
# gem 'foodsoft_uservoice', path: 'plugins/uservoice'
# gem 'foodsoft_mollie', path: 'plugins/mollie'
# gem 'foodsoft_invoices', path: 'plugins/invoices'

group :development do
gem 'listen'
Expand Down Expand Up @@ -131,4 +132,5 @@ group :test do
gem 'rswag-specs'
# plugins with tests deactivated by default
gem 'foodsoft_b85', path: 'plugins/b85'
gem 'foodsoft_invoices', path: 'plugins/invoices'
end
10 changes: 10 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ PATH
rails
ruby-filemagic

PATH
remote: plugins/invoices
specs:
foodsoft_invoices (0.0.1)
deface (~> 1.0)
prawn
prawn-table
rails

PATH
remote: plugins/links
specs:
Expand Down Expand Up @@ -659,6 +668,7 @@ DEPENDENCIES
foodsoft_b85!
foodsoft_discourse!
foodsoft_documents!
foodsoft_invoices!
foodsoft_links!
foodsoft_messages!
foodsoft_polls!
Expand Down
27 changes: 27 additions & 0 deletions app/lib/foodsoft/asset_registry.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module Foodsoft
class AssetRegistry
class << self
def stylesheets
@stylesheets ||= Set.new(['application'])
end

def javascripts
@javascripts ||= Set.new(['application_legacy'])
end

def register_stylesheet(name)
stylesheets.add(name)
end

def register_javascript(name)
javascripts.add(name)
end

def precompile_assets
(stylesheets.map { |s| "#{s}.css" } + javascripts.map { |j| "#{j}.js" }).to_a
end
end
end
end
3 changes: 2 additions & 1 deletion app/views/finance/balancing/_orders.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
%th
%tbody
- @orders.each do |order|
%tr{:class => cycle("even","odd", :name => "order")}
- row_class = cycle("even","odd", :name => "order")
%tr{:class => row_class, 'data-order_id' => order.id}
%td= link_to truncate(order.name), new_finance_order_path(order_id: order.id)
%td=h format_time(order.ends) unless order.ends.nil?
%td= order.closed? ? t('.cleared', amount: number_to_currency(order.foodcoop_result)) : t('.ended')
Expand Down
4 changes: 2 additions & 2 deletions app/views/layouts/_header.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
%meta(name="viewport" content="width=device-width, initial-scale=1.0")
%title= [t('layouts.foodsoft'), yield(:title)].join(" - ")
= csrf_meta_tags
= stylesheet_link_tag "application", :media => "all"
= stylesheet_link_tag *Foodsoft::AssetRegistry.stylesheets, media: "all"
//%link(href="images/favicon.ico" rel="shortcut icon")
= yield(:head)
= foodcoop_css_tag
Expand All @@ -20,7 +20,7 @@
\==================================================
/ Placed at the end of the document so the pages load faster
= javascript_importmap_tags
= javascript_include_tag "application_legacy"
= javascript_include_tag *Foodsoft::AssetRegistry.javascripts

:javascript
I18n.defaultLocale = "#{I18n.default_locale}";
Expand Down
7 changes: 7 additions & 0 deletions config/app_config.yml.SAMPLE
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ default: &defaults
country: Deutschland
email: foodsoft@foodcoop.test
phone: "030 323 23249"
tax_number: "12345"

# Homepage
homepage: http://www.foodcoop.test
Expand Down Expand Up @@ -105,6 +106,12 @@ default: &defaults
# Members of a user's groups and administrators can still see full names.
use_nick: false

# When use_invoices is enabled, it is possible to generate group order invoices
# in balancing view.
use_invoices: false
group_order_invoices:
vat_exempt: false

# Most plugins can be enabled/disabled here as well. Messages and wiki are enabled
# by default and need to be set to false to disable. Most other plugins needs to
# be enabled before they do anything.
Expand Down
5 changes: 5 additions & 0 deletions config/initializers/assets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
Rails.application.config.assets.precompile += %w[application_legacy.js jquery.min.js trix-editor-overrides.js]

# Add registered assets after all plugins have been initialized
Rails.application.config.after_initialize do
Rails.application.config.assets.precompile += Foodsoft::AssetRegistry.precompile_assets
end
3 changes: 3 additions & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,7 @@ de:
confirm_end: Willst Du wirklich die Bestellung %{order} beenden? Es gibt kein zurück.
new_order: Neue Bestellung anlegen
no_open_or_finished_orders: Derzeit gibt es keine laufende oder beendete Bestellungen.
not_closed: Nicht abgerechnet
orders_finished: Beendet
orders_open: Laufend
orders_settled: Abgerechnet
Expand Down Expand Up @@ -1976,6 +1977,7 @@ de:
cancel: Abbrechen
close: Schließen
confirm_delete: Willst du %{name} wirklich löschen?
confirm_mark_all: Willst du wirklich '%{name}' für alle setzen?
confirm_restore: Willst du %{name} wirklich wiederherstellen?
copy: Kopieren
delete: Löschen
Expand Down Expand Up @@ -2010,3 +2012,4 @@ de:
time:
formats:
foodsoft_datetime: "%d.%m.%Y %H:%M"
file: "%Y-%d-%B"
3 changes: 3 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,7 @@ en:
confirm_end: Do you really want to close the order %{order}? There is no going back.
new_order: Create new order
no_open_or_finished_orders: There are currently no open or closed orders.
not_closed: Not accounted
orders_finished: Closed
orders_open: Open
orders_settled: Settled
Expand Down Expand Up @@ -1981,6 +1982,7 @@ en:
cancel: Cancel
close: Close
confirm_delete: Do you really want to delete %{name}?
confirm_mark_all: Do you really want to set '%{name}' for all?
confirm_restore: Do you really want to restore %{name}?
copy: Copy
delete: Delete
Expand Down Expand Up @@ -2015,3 +2017,4 @@ en:
time:
formats:
foodsoft_datetime: "%Y-%m-%d %H:%M"
file: "%Y-%d-%B"
1 change: 1 addition & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1894,3 +1894,4 @@ es:
time:
formats:
foodsoft_datetime: "%d/%b/%Y %H:%M"
file: "%Y-%d-%B"
1 change: 1 addition & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1366,3 +1366,4 @@ fr:
time:
formats:
foodsoft_datetime: "%d/%m/%Y %H:%M"
file: "%Y-%d-%B"
3 changes: 3 additions & 0 deletions config/locales/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,7 @@ nl:
confirm_end: Wil je de bestelling %{order} werkelijk sluiten? Dit kun je niet ongedaan maken.
new_order: Nieuwe bestelling openen
no_open_or_finished_orders: Er zijn momenteel geen open of gesloten bestellingen.
not_closed: Niet afgerekend
orders_finished: Gesloten
orders_open: Open
orders_settled: Afgerekend
Expand Down Expand Up @@ -1861,6 +1862,7 @@ nl:
cancel: Annuleren
close: Sluiten
confirm_delete: Wil je %{name} echt verwijderen?
confirm_mark_all: Wil je '%{name}' echt voor iedereen instellen?
confirm_restore: Wil je %{name} echt opnieuw actief maken?
copy: Kopiëren
delete: Verwijder
Expand Down Expand Up @@ -1895,3 +1897,4 @@ nl:
time:
formats:
foodsoft_datetime: "%d-%m-%Y %H:%M"
file: "%Y-%d-%B"
1 change: 1 addition & 0 deletions config/locales/tr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1892,3 +1892,4 @@ tr:
time:
formats:
foodsoft_datetime: "%d.%b.%Y %H:%M"
file: "%Y-%d-%B"
71 changes: 71 additions & 0 deletions plugins/invoices/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Foodsoft Invoices Plugin

This plugin adds comprehensive invoice functionality to the [Foodsoft](https://github.com/foodcoops/foodsoft) system.

## Features

The plugin will provide the following features:

- Group Order Invoices - Invoices for individual group orders
- Ordergroup Invoices - Invoices that can span multiple group orders for the same ordergroup
- PDF generation for invoices
- Email notifications for invoices
- SEPA integration for payment processing
- Administrative features for invoice management

## Installation

1. Add the plugin to your Gemfile:
```ruby
gem 'foodsoft_invoices', path: 'plugins/invoices'
```

2. Run bundle install:
```
bundle install
```

3. Enable the plugin in your foodsoft configuration:
```yml
use_invoices: true
```

## Development

This plugin is currently under development. The initial version provides the basic infrastructure for the invoice functionality, with additional features to be added in subsequent releases.

## Migrations

To install the required database migrations, run the following rake task:

```
rake foodsoft_invoices_engine:install:migrations
```

Then run the migrations with:

```
rake db:migrate
```

## Configuration

The plugin provides several configuration options that can be set in your `app_config.yml`:

- `use_invoices` - Enable or disable the plugin (default: false)
- `contact.tax_number` - The tax number to be displayed on invoices
- `group_order_invoices.vat_exempt` - Set to `true` if your organization is VAT exempt (default: false)

Example configuration:

```yaml
use_invoices: true
contact:
tax_number: "123456789"
group_order_invoices:
vat_exempt: true
```

## Contact

Most of the code was originally written by @viehlieb. The code was ported to this plugin by Robert (rw@roko.li). It is part of the Foodsoft project. Original sources may be available in [Local-IT Gitlab](https://git.local-it.org/Foodsoft/foodsoft/src/branch/automatic_group_order_invoice).
20 changes: 20 additions & 0 deletions plugins/invoices/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

require 'rdoc/task'

RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'FoodsoftInvoices'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end

APP_RAKEFILE = File.expand_path('../../Rakefile', __dir__)
load 'rails/tasks/engine.rake'

Bundler::GemHelper.install_tasks
24 changes: 24 additions & 0 deletions plugins/invoices/app/assets/javascripts/foodsoft_invoices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$(document).on('ready turbolinks:load', function () {
$('.expand-trigger').click(function () {
var tableRow = $(this).closest('tr')
var orderId = tableRow.data('order_id');
var multiOrderId = tableRow.data('multi_order_id');

if(multiOrderId != undefined){
var expandedRow = $('#expanded-multi-row-' + multiOrderId);
console.log(multiOrderId);
}
else
{
var expandedRow = $('#expanded-row-' + orderId);
}
// Toggle visibility of the expanded row

expandedRow.toggleClass('hidden');

tableRow.toggleClass('border');
expandedRow.toggleClass('bordered');

return false; // Prevent the default behavior of the link
});
});
Loading
Loading