Compare commits

...

7 commits

Author SHA1 Message Date
Philipp Rothmann
2d0c163f13 merge automatic group order invoice generation
see https://github.com/foodcoops/foodsoft/pull/907 for reference
and original work by viehlieb

Co-authored-by: viehlieb <pf@pragma-shift.net>

fix PDF Pdf

make explicit deposit in invoices work

add ordergroupname to invoice file name

mark bold sum for vat exempt foodcoops

download multiple group order invoice as zip
2023-09-21 21:28:03 +02:00
Philipp Rothmann
55234b4e27 continue development after release 2023-09-09 17:01:48 +02:00
Philipp Rothmann
e194c68397 chore: bump version to 4.8.0 2023-09-09 10:52:39 +02:00
Philipp Rothmann
e1b5824830 update changelog v4.8 2023-09-09 10:52:39 +02:00
Philipp Rothmann
91f27a0a48 chore: update chrowdin translations 2023-09-04 13:01:04 +02:00
Philipp Rothmann
caa32de30c fix: rubocop violation 2023-08-23 12:47:58 +02:00
Philipp Rothmann
1e63c59a8a fix: loading trix editor overwrite in production 2023-08-23 12:17:32 +02:00
55 changed files with 1522 additions and 126 deletions

View file

@ -274,6 +274,8 @@ Lint/Void:
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 143
Exclude:
- 'app/documents/group_order_invoice_pdf.rb'
# Offense count: 13
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
@ -407,6 +409,7 @@ RSpec/Capybara/FeatureMethods:
- 'spec/integration/receive_spec.rb'
- 'spec/integration/session_spec.rb'
- 'spec/integration/supplier_spec.rb'
- 'spec/integration/group_order_invoices_spec.rb'
# Offense count: 4
RSpec/Capybara/SpecificMatcher:

View file

@ -1,3 +1,36 @@
# Foodsoft 4.8.0
* feat: Show total sums for ordergroup finances [#1017](https://github.com/foodcoops/foodsoft/pull/1017)
* feat: Richtext Messages and Attachments with Actiontext [#918](https://github.com/foodcoops/foodsoft/issues/918)
* feat: Make date configurable via locales [#997](https://github.com/foodcoops/foodsoft/pull/997)
* feat: Turkish language support added [#995](https://github.com/foodcoops/foodsoft/pull/995)
* feat: Disable member list via configuration [#990](https://github.com/foodcoops/foodsoft/pull/990)
* feat: Specify an URL to redirect after logout via settings #989
* feat: introduce importmaps [#983](https://github.com/foodcoops/foodsoft/pull/983)
* feat: ruby 2.7.2 and rails 7 upgrade [#979](https://github.com/foodcoops/foodsoft/pull/979)
* feat: Add home controller test [#972](https://github.com/foodcoops/foodsoft/pull/972)
* feat: Replace apivore with rswag for api tests [#969](https://github.com/foodcoops/foodsoft/pull/969)
* feat: increase test coverage [#966](https://github.com/foodcoops/foodsoft/pull/966)
* feat: Show order note as tooltip [#965](https://github.com/foodcoops/foodsoft/pull/965)
* feat: Add sd_notify [#961](https://github.com/foodcoops/foodsoft/pull/961)
* feat: Show instance name at login screen [#957](https://github.com/foodcoops/foodsoft/pull/957)
* feat: Enabled systemd socket activation [#942](https://github.com/foodcoops/foodsoft/pull/942)
* feat: Add table_print gem for debugging ActiveRecord queries in the console [#935](https://github.com/foodcoops/foodsoft/pull/935)
* feat: Add admin UI for SupplierCategories (supplier_categories) [#930](https://github.com/foodcoops/foodsoft/pull/930)
* fix: add null checks for articles convert_units [33034e6](https://github.com/foodcoops/foodsoft/commit/33034e66b88968dedc5289425e1eff847ee67e12)
* fix: downgrade haml to make deface work [#1003](https://github.com/foodcoops/foodsoft/pull/1003)
* fix: dutch translation errors [#954](https://github.com/foodcoops/foodsoft/pull/954)
* fix: Fixe filtering of active ordergroups [#934](https://github.com/foodcoops/foodsoft/pull/934)
* fix: Change password validation to allow longer passwords [#923](https://github.com/foodcoops/foodsoft/pull/923)
* fix: Invoice: change label "delivery" to "stock delivery" [#922](https://github.com/foodcoops/foodsoft/pull/922)
* fix: Allow decimal numbers in transaction collections [#921](https://github.com/foodcoops/foodsoft/pull/921)
* fix: Add validation of more article fields [#917](https://github.com/foodcoops/foodsoft/pull/917/files)
* fix: Add default time_zone [#912](https://github.com/foodcoops/foodsoft/pull/912)
* fix: Rename Piwik to Matomo [#911](https://github.com/foodcoops/foodsoft/pull/911/files)
* fix: Change instructions to rbenv [#910](https://github.com/foodcoops/foodsoft/pull/910/files)
# Foodsoft 4.7.1
(31 December 2020)

View file

@ -1 +1 @@
4.7.99
4.8.99

View file

@ -241,6 +241,9 @@ table {
tr.order-article:hover .article-info {
display: none;
}
tr.order-article:focus .article-info {
display: none;
}
}
#order-footer {
@ -275,11 +278,13 @@ tr.order-article .article-info {
display: none;
}
tr.order-article:hover .article-info {
tr.order-article:focus{
background-color: #E4EED6;
}
tr.order-article:focus .article-info {
display: block;
}
// ********* Articles
tr.just-updated {

View file

@ -0,0 +1,17 @@
module Concerns::SendGroupOrderInvoicePdf
extend ActiveSupport::Concern
protected
def create_invoice_pdf(group_order_invoice)
invoice_data = group_order_invoice.load_data_for_invoice
invoice_data[:title] = t('documents.group_order_invoice_pdf.title', supplier: invoice_data[:supplier])
invoice_data[:no_footer] = true
GroupOrderInvoicePdf.new invoice_data
end
def send_group_order_invoice_pdf(group_order_invoice)
pdf = create_invoice_pdf(group_order_invoice)
send_data pdf.to_pdf, filename: pdf.filename, type: 'application/pdf'
end
end

View file

@ -5,7 +5,7 @@ class Finance::BalancingController < Finance::BaseController
def new
@order = Order.find(params[:order_id])
flash.now.alert = t('.alert') if @order.closed?
flash.now.alert = t('finance.balancing.new.alert') if @order.closed? && flash[:alert].blank?
@comments = @order.comments
@articles = @order.order_articles.ordered_or_member.includes(:article, :article_price,
@ -81,9 +81,24 @@ class Finance::BalancingController < Finance::BaseController
@order = Order.find(params[:id])
@type = FinancialTransactionType.find_by_id(params.permit(:type)[:type])
@order.close!(@current_user, @type)
redirect_to finance_order_index_url, notice: t('.notice')
rescue StandardError => e
redirect_to new_finance_order_url(order_id: @order.id), alert: t('.alert', message: e.message)
note = t('finance.balancing.close.notice')
if @order.closed?
alert = t('finance.balancing.close.alert')
if FoodsoftConfig[:group_order_invoices]&.[](:use_automatic_invoices)
@order.group_orders.each do |go|
alert = t('finance.balancing.close.settings_not_set')
goi = GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
if goi.save!
NotifyGroupOrderInvoiceJob.perform_later(goi)
note = t('finance.balancing.close.notice_mail')
end
end
end
end
alert ||= t('finance.balancing.close.alert')
redirect_to finance_order_index_url, notice: note
rescue => error
redirect_to new_finance_order_url(order_id: @order.id), notice: note, alert: alert, msg: error.message
end
# Close the order directly, without automaticly updating ordergroups account balances

View file

@ -0,0 +1,87 @@
class GroupOrderInvoicesController < ApplicationController
include Concerns::SendGroupOrderInvoicePdf
before_action :authenticate_finance
def show
begin
@group_order_invoice = GroupOrderInvoice.find(params[:id])
if FoodsoftConfig[:contact][:tax_number]
respond_to do |format|
format.pdf do
send_group_order_invoice_pdf @group_order_invoice if FoodsoftConfig[:contact][:tax_number]
end
end
else
raise RecordInvalid
end
rescue ActiveRecord::RecordInvalid => error
redirect_back fallback_location: root_path, notice: 'Something went wrong', alert: I18n.t('errors.general_msg', msg: "#{error} " + I18n.t('errors.check_tax_number'))
end
end
def destroy
goi = GroupOrderInvoice.find(params[:id])
@order = goi.group_order.order
goi.destroy
respond_to do |format|
format.js
format.json { head :no_content }
end
end
def create_multiple
invoice_date = params[:group_order_invoice][:invoice_date]
order_id = params[:group_order_invoice][:order_id]
@order = Order.find(order_id)
gos = GroupOrder.where("order_id = ?", order_id)
gos.each do |go|
goi = GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
goi.invoice_date = invoice_date
goi.invoice_number = goi.generate_invoice_number(1)
goi.save!
end
respond_to do |format|
format.js
end
end
def create
go = GroupOrder.find(params[:group_order])
@order = go.order
GroupOrderInvoice.find_or_create_by!(group_order_id: go.id)
respond_to do |format|
format.js
end
redirect_back fallback_location: root_path
rescue => error
redirect_back fallback_location: root_path, notice: 'Something went wrong', :alert => I18n.t('errors.general_msg', :msg => error)
end
def download_all
order = Order.find(params[:order_id])
invoices = order.group_orders.map(&:group_order_invoice)
pdf = {}
temp_file = Tempfile.new("all_invoices_for_order_#{order.id}.zip")
Zip::File.open(temp_file.path, Zip::File::CREATE) do |zipfile|
invoices.each do |invoice|
pdf = create_invoice_pdf(invoice)
invoice_file = Tempfile.new("#{pdf.filename}")
File.open(invoice_file.path, 'w:ASCII-8BIT') do |file|
file.write(pdf.to_pdf)
end
zipfile.add("#{pdf.filename}", invoice_file.path) unless zipfile.find_entry("#{pdf.filename}")
end
end
zip_data = File.read(temp_file.path)
respond_to do |format|
format.html {
send_data(zip_data, type: 'application/zip', filename: "#{l order.ends, format: :file}-#{order.supplier.name}-#{order.id}.zip", disposition: 'attachment')
}
end
end
end

View file

@ -0,0 +1,264 @@
class GroupOrderInvoicePdf < RenderPdf
def filename
ordergroup_name = @options[:ordergroup].name || "OrderGroup"
"#{ordergroup_name}_" + I18n.t('documents.group_order_invoice_pdf.filename', :number => @options[:invoice_number]) + '.pdf'
end
def title
I18n.t('documents.group_order_invoice_pdf.title', :supplier => @options[:supplier])
end
def body
contact = FoodsoftConfig[:contact].symbolize_keys
ordergroup = @options[:ordergroup]
# From paragraph
bounding_box [margin_box.right - 200, margin_box.top - 20], width: 200 do
text I18n.t('documents.group_order_invoice_pdf.invoicer')
move_down 7
text FoodsoftConfig[:name], size: fontsize(9), align: :left
move_down 5
text contact[:street], size: fontsize(9), align: :left
move_down 5
text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :left
move_down 5
if contact[:phone].present?
text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :left
move_down 5
end
text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :left if contact[:email].present?
move_down 5
text I18n.t('documents.group_order_invoice_pdf.tax_number', :number => @options[:tax_number]), size: fontsize(9), align: :left
end
# Receiving Ordergroup
bounding_box [margin_box.left, margin_box.top - 20], width: 200 do
text I18n.t('documents.group_order_invoice_pdf.invoicee')
move_down 7
text I18n.t('documents.group_order_invoice_pdf.ordergroup.name', ordergroup: ordergroup.name.to_s), size: fontsize(9)
move_down 5
if ordergroup.contact_address.present?
text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_address', contact_address: ordergroup.contact_address.to_s), size: fontsize(9)
move_down 5
end
if ordergroup.contact_phone.present?
text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_phone', contact_phone: ordergroup.contact_phone.to_s), size: fontsize(9)
move_down 5
end
if ordergroup.customer_number.present?
text I18n.t('documents.group_order_invoice_pdf.ordergroup.customer_number', customer_number: ordergroup.customer_number.to_s), size: fontsize(9)
move_down 5
end
end
# invoice Date and nnvoice number
bounding_box [margin_box.right - 200, margin_box.top - 150], width: 200 do
text I18n.t('documents.group_order_invoice_pdf.invoice_date', invoice_date: @options[:invoice_date].strftime(I18n.t('date.formats.default'))), align: :left
move_down 5
text I18n.t('documents.group_order_invoice_pdf.invoice_number', invoice_number: @options[:invoice_number]), align: :left
end
move_down 15
# kind of the "body" of the invoice
text I18n.t('documents.group_order_invoice_pdf.payment_method', payment_method: @options[:payment_method])
move_down 15
text I18n.t('documents.group_order_invoice_pdf.table_headline')
move_down 5
#------------- Table Data -----------------------
@group_order = GroupOrder.find(@options[:group_order].id)
if FoodsoftConfig[:group_order_invoices][:vat_exempt]
body_for_vat_exempt
else
body_with_vat
end
end
def body_for_vat_exempt
total_gross = 0
data = [I18n.t('documents.group_order_invoice_pdf.vat_exempt_rows')]
move_down 10
group_order_articles = GroupOrderArticle.where(group_order_id: @group_order.id)
separate_deposits = FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
group_order_articles.each do |goa|
# if no unit is received, nothing is to be charged
next if goa.result.to_i == 0
goa_total_price = separate_deposits ? goa.total_price_without_deposit : goa.total_price
data << [goa.order_article.article.name,
goa.result.to_i,
number_to_currency(goa.order_article.price.fc_price_without_deposit),
number_to_currency(goa_total_price)]
total_gross += goa_total_price
next unless separate_deposits && goa.order_article.price.deposit > 0.0
goa_total_deposit = goa.result * goa.order_article.price.fc_deposit_price
data << ["zzgl. Pfand",
goa.result.to_i,
number_to_currency(goa.order_article.article.fc_deposit_price),
number_to_currency(goa_total_deposit)]
total_gross += goa_total_deposit
end
table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
table.header = true
table.position = :center
table.cells.border_width = 1
table.cells.border_color = '666666'
table.row(0).column(0..4).width = 80
table.row(0).border_bottom_width = 2
table.columns(1).align = :right
table.columns(1..6).align = :right
end
move_down 5
sum = []
sum << [nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_gross'), number_to_currency(total_gross)]
# table for sum
table sum, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
table.header = true
table.position = :center
table.cells.border_width = 1
table.cells.border_color = '666666'
table.row(0).columns(2..4).style(align: :bottom)
table.row(0).border_bottom_width = 2
table.row(0..-1).columns(0..1).border_width = 0
table.rows(0..-1).columns(0..4).width = 80
table.row(0).column(-1).style(font_style: :bold)
table.row(0).column(-2).style(font_style: :bold)
table.row(0).column(-1).size = fontsize(10)
table.row(0).column(-2).size = fontsize(10)
table.columns(1).align = :right
table.columns(1..6).align = :right
end
move_down 25
text I18n.t('documents.group_order_invoice_pdf.small_business_regulation')
move_down 10
end
def body_with_vat
separate_deposits = FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
total_gross = 0
total_net = 0
# Articles
tax_hash_net = Hash.new(0) # for summing up article net prices grouped into vat percentage
tax_hash_gross = Hash.new(0) # same here with gross prices
if separate_deposits
total_deposit = 0
total_deposit_gross = 0
tax_hash_deposit_gross = Hash.new(0) # for summing up deposit gross prices grouped into vat percentage
tax_hash_deposit_net = Hash.new(0) # same here with gross prices
end
marge = FoodsoftConfig[:price_markup]
# data table looks different when price_markup > 0
data = if marge == 0
[I18n.t('documents.group_order_invoice_pdf.no_price_markup_rows')]
else
[I18n.t('documents.group_order_invoice_pdf.price_markup_rows', marge: marge)]
end
goa_tax_hash = GroupOrderArticle.where(group_order_id: @group_order.id).find_each.group_by { |oat| oat.order_article.price.tax }
goa_tax_hash.each do |tax, group_order_articles|
group_order_articles.each do |goa|
# if no unit is received, nothing is to be charged
next if goa.result.to_i == 0
order_article = goa.order_article
goa_total_net = goa.result * order_article.price.price
goa_total_gross = separate_deposits ? goa.total_price_without_deposit : goa.total_price
data << [order_article.article.name,
goa.result.to_i,
number_to_currency(order_article.price.price),
number_to_currency(goa_total_net),
tax.to_s + '%',
number_to_currency(goa_total_gross)]
if separate_deposits && order_article.price.deposit > 0.0
goa_deposit = goa.result * order_article.price.deposit
goa_total_deposit = goa.result * order_article.price.fc_deposit_price
data << ["zzgl. Pfand",
goa.result.to_i,
number_to_currency(order_article.price.deposit),
number_to_currency(goa_deposit),
tax.to_s + '%',
number_to_currency(goa_total_deposit)]
total_deposit += goa_deposit
total_deposit_gross += goa_total_deposit
tax_hash_deposit_net[tax.to_i] += goa_deposit
tax_hash_deposit_gross[tax.to_i] += goa_total_deposit
end
tax_hash_net[tax.to_i] += goa_total_net
tax_hash_gross[tax.to_i] += goa_total_gross
total_net += goa_total_net
total_gross += goa_total_gross
end
end
# Two separate tables for sum and individual data
# article information + data
table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
table.header = true
table.position = :center
table.cells.border_width = 1
table.cells.border_color = '666666'
table.row(0).columns(0..6).style(background_color: 'cccccc', font_style: :bold)
table.rows(0..-1).columns(0..6).width = 80
table.row(0).border_bottom_width = 2
table.columns(1).align = :right
table.columns(1..6).align = :right
end
sum = [[nil, nil, nil, "Netto", "MwSt", "Brutto"]]
[7, 19].each do |key|
sum << [nil, nil, "Produkte mit #{key}%", number_to_currency(tax_hash_net[key]), number_to_currency(tax_hash_gross[key] - tax_hash_net[key]), number_to_currency(tax_hash_gross[key])]
sum << [nil, nil, "Pfand mit #{key}%", number_to_currency(tax_hash_deposit_net[key]), number_to_currency(tax_hash_deposit_gross[key] - tax_hash_deposit_net[key]), number_to_currency(tax_hash_deposit_gross[key])] if separate_deposits
end
total_deposit_gross ||= 0
sum << [nil, nil, nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_gross'), number_to_currency(total_gross + total_deposit_gross)]
move_down 10
table sum, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table|
table.header = true
table.position = :center
table.cells.border_width = 1
table.cells.border_color = '666666'
table.row(0).columns(2..6).style(align: :bottom)
table.row(0).border_bottom_width = 2
table.row(0..-1).columns(0..1).border_width = 0
table.rows(0..-1).columns(0..6).width = 80
table.row(-1).column(-1).style(font_style: :bold)
table.row(-1).column(-2).style(font_style: :bold)
table.row(-1).column(-1).size = fontsize(10)
table.row(-1).column(-2).size = fontsize(10)
table.columns(1).align = :right
table.columns(1..6).align = :right
end
if FoodsoftConfig[:group_order_invoices][:vat_exempt]
move_down 15
text I18n.t('documents.group_order_invoice_pdf.small_business_regulation')
end
move_down 10
end
end

View file

@ -1,4 +1,4 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "trix"
import "@rails/actiontext"
import "./trix-editor-overrides"
import "trix-editor-overrides"

View file

@ -0,0 +1,10 @@
class NotifyGroupOrderInvoiceJob < ApplicationJob
def perform(group_order_invoice)
ordergroup = group_order_invoice.group_order.ordergroup
ordergroup.users.each do |user|
Mailer.deliver_now_with_user_locale user do
Mailer.group_order_invoice(group_order_invoice, user)
end
end
end
end

View file

@ -70,7 +70,7 @@ class RenderPdf < Prawn::Document
options[:skip_page_creation] = true
@options = options
@first_page = true
no_footer = @options&.[](:no_footer) ? true : false
super(options)
# Use ttf for better utf-8 compability
@ -84,11 +84,11 @@ class RenderPdf < Prawn::Document
)
header = options[:title] || title
footer = I18n.l(Time.now, format: :long)
footer = I18n.l(Time.now, format: :long) unless no_footer
header_size = 0
header_size = height_of(header, size: HEADER_FONT_SIZE, font: DEFAULT_FONT) + HEADER_SPACE if header
footer_size = height_of(footer, size: FOOTER_FONT_SIZE, font: DEFAULT_FONT) + FOOTER_SPACE
footer_size = no_footer ? 0 : height_of(footer, size: FOOTER_FONT_SIZE, font: DEFAULT_FONT) + FOOTER_SPACE
start_new_page(top_margin: TOP_MARGIN + header_size, bottom_margin: BOTTOM_MARGIN + footer_size)
@ -98,12 +98,15 @@ class RenderPdf < Prawn::Document
bounding_box [bounds.left, bounds.top + header_size], width: bounds.width, height: header_size do
text header, size: HEADER_FONT_SIZE, align: :center, overflow: :shrink_to_fit if header
end
font_size FOOTER_FONT_SIZE do
bounding_box [bounds.left, bounds.bottom - FOOTER_SPACE], width: bounds.width, height: footer_size do
text footer, align: :left, valign: :bottom
end
bounding_box [bounds.left, bounds.bottom - FOOTER_SPACE], width: bounds.width, height: footer_size do
text I18n.t('lib.render_pdf.page', number: page_number, count: page_count), align: :right, valign: :bottom
unless no_footer
font_size FOOTER_FONT_SIZE do
bounding_box [bounds.left, bounds.bottom - FOOTER_SPACE], width: bounds.width, height: footer_size do
text footer, align: :left, valign: :bottom
end
bounding_box [bounds.left, bounds.bottom - FOOTER_SPACE], width: bounds.width, height: footer_size do
text I18n.t('lib.render_pdf.page', number: page_number, count: page_count), align: :right, valign: :bottom
end
end
end
end

View file

@ -51,6 +51,18 @@ class Mailer < ActionMailer::Base
subject: I18n.t('mailer.welcome.subject')
end
# Sends automatically generated invoicesfor group orders to ordergroup members
def group_order_invoice(group_order_invoice, user)
@user = user
@group_order_invoice = group_order_invoice
@group_order = group_order_invoice.group_order
@supplier = @group_order.order.supplier.name
@group = @group_order.ordergroup
add_group_order_invoice_attachments(group_order_invoice)
mail to: user,
subject: I18n.t('mailer.group_order_invoice.subject', group: @group.name, supplier: @supplier)
end
# Sends order result for specific Ordergroup
def order_result(user, group_order)
@order = group_order.order
@ -169,6 +181,11 @@ class Mailer < ActionMailer::Base
attachments['order.csv'] = OrderCsv.new(order, options).to_csv
end
def add_group_order_invoice_attachments(group_order_invoice)
attachment_name = group_order_invoice.name + '.pdf'
attachments[attachment_name] = GroupOrderInvoicePdf.new(group_order_invoice.load_data_for_invoice).to_pdf
end
# separate method to allow plugins to mess with the text
def additonal_welcome_text(user); end

View file

@ -7,11 +7,27 @@ module PriceCalculation
add_percent(price + deposit, tax)
end
def gross_price_without_deposit
add_percent(price, tax)
end
def gross_deposit_price
add_percent(deposit, tax)
end
# @return [Number] Price for the foodcoop-member.
def fc_price
add_percent(gross_price, FoodsoftConfig[:price_markup].to_i)
end
def fc_price_without_deposit
add_percent(gross_price_without_deposit, FoodsoftConfig[:price_markup].to_i)
end
def fc_deposit_price
add_percent(gross_deposit_price, FoodsoftConfig[:price_markup].to_i)
end
private
def add_percent(value, percent)

View file

@ -9,6 +9,7 @@ class GroupOrder < ApplicationRecord
has_many :group_order_articles, dependent: :destroy
has_many :order_articles, through: :group_order_articles
has_one :financial_transaction
has_one :group_order_invoice
belongs_to :updated_by, optional: true, class_name: 'User', foreign_key: 'updated_by_user_id'
validates :order_id, presence: true

View file

@ -208,6 +208,18 @@ class GroupOrderArticle < ApplicationRecord
end
end
def total_price_without_deposit(order_article = self.order_article)
if order_article.order.open?
if FoodsoftConfig[:tolerance_is_costly]
order_article.price.fc_price_without_deposit * (quantity + tolerance)
else
order_article.price.fc_price_without_deposit * quantity
end
else
order_article.price.fc_price_without_deposit * result
end
end
# Check if the result deviates from the result_computed
def result_manually_changed?
result != result_computed unless result.nil?

View file

@ -0,0 +1,58 @@
class GroupOrderInvoice < ApplicationRecord
belongs_to :group_order
validates_presence_of :group_order
validates_uniqueness_of :invoice_number
validate :tax_number_set
after_initialize :init, unless: :persisted?
def generate_invoice_number(count)
trailing_number = count.to_s.rjust(4, '0')
if GroupOrderInvoice.find_by(invoice_number: self.invoice_date.strftime("%Y%m%d") + trailing_number)
generate_invoice_number(count.to_i + 1)
else
self.invoice_date.strftime("%Y%m%d") + trailing_number
end
end
def tax_number_set
if FoodsoftConfig[:contact][:tax_number].blank?
errors.add(:group_order_invoice, "Keine Steuernummer in FoodsoftConfig :contact gesetzt")
end
end
def init
self.invoice_date = Time.now unless invoice_date
self.invoice_number = generate_invoice_number(1) unless self.invoice_number
self.payment_method = FoodsoftConfig[:group_order_invoices]&.[](:payment_method) || I18n.t('activerecord.attributes.group_order_invoice.payment_method') unless self.payment_method
end
def name
I18n.t('activerecord.attributes.group_order_invoice.name') + "_#{invoice_number}"
end
def load_data_for_invoice
invoice_data = {}
order = group_order.order
invoice_data[:supplier] = order.supplier.name
invoice_data[:ordergroup] = group_order.ordergroup
invoice_data[:group_order] = group_order
invoice_data[:invoice_number] = invoice_number
invoice_data[:invoice_date] = invoice_date
invoice_data[:tax_number] = FoodsoftConfig[:contact][:tax_number]
invoice_data[:payment_method] = payment_method
invoice_data[:order_articles] = {}
group_order.order_articles.each do |order_article|
# Get the result of last time ordering, if possible
goa = group_order.group_order_articles.detect { |tmp_goa| tmp_goa.order_article_id == order_article.id }
# Build hash with relevant data
invoice_data[:order_articles][order_article.id] = {
:price => order_article.article.fc_price,
:quantity => (goa ? goa.quantity : 0),
:total_price => (goa ? goa.total_price : 0),
:tax => order_article.article.tax
}
end
invoice_data
end
end

View file

@ -207,7 +207,7 @@ class Order < ApplicationRecord
# :fc, guess what...
def sum(type = :gross)
total = 0
if %i[net gross fc].include?(type)
if %i[net gross gross_deposit fc_deposit deposit fc].include?(type)
for oa in order_articles.ordered.includes(:article, :article_price)
quantity = oa.units * oa.price.unit_quantity
case type
@ -217,6 +217,12 @@ class Order < ApplicationRecord
total += quantity * oa.price.gross_price
when :fc
total += quantity * oa.price.fc_price
when :gross_deposit
total += quantity * oa.price.gross_deposit_price
when :fc_deposit
total += quantity * oa.price.fc_deposit_price
when :deposit
total += quantity * oa.price.deposit
end
end
elsif %i[groups groups_without_markup].include?(type)
@ -224,7 +230,11 @@ class Order < ApplicationRecord
for goa in go.group_order_articles
case type
when :groups
total += goa.result * goa.order_article.price.fc_price
total += if FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
goa.result * (goa.order_article.price.fc_price + goa.order_article.price.fc_deposit_price)
else
goa.result * goa.order_article.price.fc_price
end
when :groups_without_markup
total += goa.result * goa.order_article.price.gross_price
end

View file

@ -7,4 +7,5 @@
= config_input c, :country, as: :string, input_html: {class: 'input-xlarge'}
= config_input c, :email, required: true, input_html: {class: 'input-xlarge'}
= config_input c, :phone, input_html: {class: 'input-medium'}
= config_input c, :tax_number, input_html: {class: 'input-medium'}
= config_input form, :homepage, required: true, as: :url, input_html: {class: 'input-xlarge'}

View file

@ -13,6 +13,12 @@
= config_input form, :charge_members_manually, as: :boolean
= config_input form, :use_iban, as: :boolean
= config_input form, :use_self_service, as: :boolean
%h4= t '.group_order_invoices'
= form.fields_for :group_order_invoices do |field|
= config_input field, :use_automatic_invoices, as: :boolean
= config_input field, :separate_deposits, as: :boolean
= config_input field, :vat_exempt, as: :boolean
= config_input field, :payment_method, as: :string, input_html: {class: 'input-medium'}
%h4= t '.schedule_title'
= form.simple_fields_for :order_schedule do |fields|

View file

@ -2,6 +2,7 @@
%p= t('.first_paragraph', url: link_to(t('.here'), new_invite_path(id: @ordergroup.id), remote: true)).html_safe
= simple_form_for [:admin, @ordergroup] do |f|
- captured = capture do
= f.input :customer_number
= f.input :contact_person
= f.input :contact_phone
= f.input :contact_address

View file

@ -9,6 +9,8 @@
%th= t('.end')
%th= t('.state')
%th= heading_helper Order, :updated_by
%th= heading_helper GroupOrderInvoice, :name
%th
%th
%tbody
- @orders.each do |order|
@ -17,6 +19,14 @@
%td=h format_time(order.ends) unless order.ends.nil?
%td= order.closed? ? t('.cleared', amount: number_to_currency(order.foodcoop_result)) : t('.ended')
%td= show_user(order.updated_by)
%td{id: "generate-invoice#{order.id}"}
- if order.closed?
-if FoodsoftConfig[:contact][:tax_number] && order.ordergroups.present?
= render :partial => 'group_order_invoices/links', locals:{order: order}
-else
= I18n.t('activerecord.attributes.group_order_invoice.tax_number_not_set')
- else
= t('orders.index.not_closed')
%td
- unless order.closed?
- if current_user.role_orders?

View file

@ -12,6 +12,16 @@
%tr
%td= t('.fc_amount')
%td.numeric= number_to_currency(order.sum(:fc))
- if FoodsoftConfig[:group_order_invoices]&.[](:separate_deposits)
%tr
%td= t('.deposit')
%td.numeric= number_to_currency(order.sum(:deposit))
%tr
%td= t('.gross_deposit')
%td.numeric= number_to_currency(order.sum(:gross_deposit))
%tr
%td= t('.fc_deposit')
%td.numeric= number_to_currency(order.sum(:fc_deposit))
%tr
%td= t('.groups_amount')
%td.numeric= number_to_currency(order.sum(:groups))

View file

@ -1,5 +1,4 @@
- title t('.title')
- content_for :actionbar do
- if FoodsoftConfig[:charge_members_manually]
= link_to t('.close_all_direct_with_invoice'), close_all_direct_with_invoice_finance_order_index_path, method: :post, class: 'btn'

View file

@ -0,0 +1,29 @@
.row
.column.small-12
- show_generate_with_date = true
- order.group_orders.each do |go|
- if go.group_order_invoice.present?
- show_generate_with_date = false
- if show_generate_with_date
= form_for :group_order_invoice, url: url_for('group_order_invoice#create_multiple'), remote: true do |f|
= f.label :invoice_date, I18n.t('activerecord.attributes.group_order_invoice.links.invoice_date')
= f.date_field :invoice_date, {value: Date.today, max: Date.today, required: true}
= f.hidden_field :order_id, value: order.id
= f.submit I18n.t('activerecord.attributes.group_order_invoice.links.generate_with_date'), class: 'btn btn small'
- order.group_orders.includes([:group_order_invoice, :ordergroup]).each do |go|
.row
.column.small-3
= label_tag go.ordergroup.name
- if go.group_order_invoice
.column.small-3
= link_to I18n.t('activerecord.attributes.group_order_invoice.links.download'), group_order_invoice_path(go.group_order_invoice, :format => 'pdf'), class: 'btn btn-small'
.column.small-3
= link_to I18n.t('activerecord.attributes.group_order_invoice.links.delete'), go.group_order_invoice, method: :delete, class: 'btn btn-danger btn-small', remote: true
- else
= button_to I18n.t('activerecord.attributes.group_order_invoice.links.generate'), group_order_invoices_path(:method => :post, group_order: go) ,class: 'btn btn-small', params: {id: order.id}, remote: true
- if order.group_orders.map(&:group_order_invoice).compact.present?
%br/
.row
.column.small-3
= link_to I18n.t('activerecord.attributes.group_order_invoice.links.download_all_zip'), download_all_group_order_invoices_path(order), class: 'btn btn-small'

View file

@ -0,0 +1 @@
$("#generate-invoice<%= params[:id] %>").html("<%= escape_javascript(render partial: 'links', locals: {order: @order}) %>");

View file

@ -0,0 +1 @@
$("#generate-invoice<%= @order.id %>").html("<%= escape_javascript(render partial: 'links', locals: {order: @order}) %>");

View file

@ -0,0 +1 @@
$("#generate-invoice<%= @order.id %>").html("<%= escape_javascript(render partial: 'links', locals: {order: @order}) %>");

View file

@ -69,7 +69,7 @@
= f.hidden_field :order_id
= f.hidden_field :updated_by_user_id
= f.hidden_field :ordergroup_id
%table.table.table-hover
%table.table
%thead
%tr
%th= heading_helper Article, :name
@ -94,7 +94,7 @@
%i.icon-tag
%td{colspan: "9"}
- order_articles.each do |order_article|
%tr{class: "#{cycle('even', 'odd', name: 'articles')} order-article #{get_missing_units_css_class(@ordering_data[:order_articles][order_article.id][:missing_units])}", valign: "top"}
%tr{class: "#{cycle('even', 'odd', name: 'articles')} order-article #{get_missing_units_css_class(@ordering_data[:order_articles][order_article.id][:missing_units])}", valign: "top", tabindex: "0"}
%td.name= order_article.article.name
- if @order.stockit?
%td= truncate order_article.article.supplier.name, length: 15

View file

@ -0,0 +1 @@
= raw t '.text', group: @group.name, supplier: @supplier , foodcoop: FoodsoftConfig[:name]

View file

@ -57,6 +57,10 @@
= f.label :contact_person
%br/
= f.text_field :contact_person
%p
= f.label :customer_number
%br/
= f.text_field :customer_number
%p
= f.label :contact_phone
%br/

View file

@ -6,6 +6,8 @@
%dd=h group.contact
%dt= heading_helper(Ordergroup, :contact_address) + ':'
%dd= link_to_gmaps group.contact_address
%dt= heading_helper(Ordergroup, :customer_number) + ':'
%dd=h group.customer_number
- if group.break_start? or group.break_end?
%dt= heading_helper(Ordergroup, :break) + ':'
%dd= raw t '.break', start: format_date(group.break_start), end: format_date(group.break_end)

View file

@ -2,3 +2,4 @@
pin "application", preload: true
pin "trix"
pin "@rails/actiontext", to: "actiontext.js"
pin "trix-editor-overrides"

View file

@ -9,4 +9,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets.
# 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]
Rails.application.config.assets.precompile += %w[application_legacy.js jquery.min.js trix-editor-overrides.js]

View file

@ -90,6 +90,17 @@ de:
tolerance: Toleranz
total_price: Summe
unit_price: Preis/Einheit
group_order_invoice:
name: Bestellgruppenrechnung
links:
delete: Rechnung löschen
download: Rechnung herunterladen
generate: Rechnung erzeugen
invoice_date: Datum der Bestellgruppenrechnung
generate_with_date: setzen & erzeugen
download_all_zip: Alle Rechnungen herunterladen (zip)
payment_method: Guthaben
tax_number_not_set: Steuernummer in den Einstellungen nicht gesetzt
invoice:
amount: Betrag
attachment: Anhang
@ -158,6 +169,7 @@ de:
contact_address: Adresse
contact_person: Kontaktperson
contact_phone: Telefon
customer_number: Kundennummer
description: Beschreibung
ignore_apple_restriction: Bestellstop bei zu wenig Äpfeln ignorieren
last_order: Zuletzt bestellt
@ -318,6 +330,7 @@ de:
emails_title: E-Mails versenden
tab_payment:
schedule_title: Bestellschema
group_order_invoices: Bestellgruppenrechnungen
tab_security:
default_roles_title: Zugriff auf
default_roles_paragraph: Jedes Mitglied der Foodcoop hat automatisch Zugriff auf folgende Bereiche.
@ -448,6 +461,7 @@ de:
error_denied_sign_in: als ein anderer Benutzer anmelden
error_feature_disabled: Diese Funktion ist derzeit nicht aktiviert.
error_members_only: Diese Aktion ist nur für Mitglieder der Gruppe erlaubt!
error_minimum_balance: Ihr Kontostand liegt leider unter dem Minimum von %{min}.
error_token: Zugriff verweigert (ungültiger Token)!
article_categories:
create:
@ -602,6 +616,10 @@ de:
email_from: E-Mails werden so aussehen, als ob sie von dieser Adresse gesendet wurden. Kann leer gelassen werden, um die Kontaktadresse der Foodcoop zu benutzen.
email_replyto: Setze diese Adresse, wenn Du Antworten auf Foodsoft E-Mails auf eine andere, als die oben angegebene Absenderadresse bekommen möchtest.
email_sender: E-Mails werden so aussehen, als ob sie von dieser Adresse versendet wurden. Um zu vermeiden, dass E-Mails dadurch als Spam eingeordnet werden, muss der Webserver möglicherweise im SPF Eintrag der Domain der E-Mail Adresse eingetragen werden.
group_order_invoices:
use_automativ_go_invoices: Es werden auf die Bestellgruppen zugeschnittene Rechnungen für die jeweilige Bestellung beim Klicken auf "abrechnen" an alle Bestellgruppenmitglieder per Mail versendet.
payment_method: Zahlungsart wird auf der Bestellgruppenrechnung deklariert
vat_exempt: Eine Auflistung der Rechnungsartikel erfolgt ohne explizite Ausweisung der MwSt. und die Rechnung erhält den notwendigen Zusatz bzgl. der Kleinunternehmerregelung §19 (FoodCoop Marge ebenfalls nicht in Rechnung enthalten)
help_url: Link zur Dokumentationsseite
homepage: Webseite der Foodcoop
ignore_browser_locale: Ignoriere die Sprache des Computers des Anwenders, wenn der Anwender noch keine Sprache gewählt hat.
@ -644,6 +662,7 @@ de:
phone: Telefon
street: Straße
zip_code: Postleitzahl
tax_number: Steuernummer
currency_space: Leerzeichen hinzufügen
currency_unit: Währung
custom_css: Angepasstes CSS
@ -659,6 +678,11 @@ de:
email_from: Absenderadresse
email_replyto: Antwortadresse
email_sender: Senderadresse
group_order_invoices:
use_automatic_invoices: Automatisch bei Abrechnung per Mail versenden
separate_deposits: Pfand getrennt abrechnen
payment_method: Zahlungsart
vat_exempt: Diese Foodcoop ist MwSt. befreit
help_url: URL Dokumentation
homepage: Webseite
ignore_browser_locale: Browsersprache ignorieren
@ -697,6 +721,7 @@ de:
applications: Apps
foodcoop: Foodcoop
language: Sprache
layout: Layout
list: Liste
messages: Nachrichten
others: Sonstiges
@ -744,6 +769,47 @@ de:
update:
notice: Lieferung wurde aktualisiert.
documents:
group_order_invoice_pdf:
filename: Rechnung%{number}
invoicer: Rechnungsteller*in
invoicee: Rechnungsempfänger*in
invoice_date: 'Rechnungsdatum: %{invoice_date}'
invoice_number: 'Rechnungsnummer: %{invoice_number}'
markup_included: zzgl. Foodcoop Marge auf brutto Preis %{marge}%
ordergroup:
contact_phone: 'Telefonnummer: %{contact_phone}'
contact_address: 'Adresse : %{contact_address}'
customer_number: 'Kundennummer: %{customer_number}'
name: Bestellgruppe %{ordergroup}
payment_method: 'Zahlungsart: %{payment_method}'
sum_to_pay: Zu zahlen gesamt
sum_to_pay_net: Zu zahlen gesamt (netto)
sum_to_pay_gross: Gesamt
small_business_regulation: Als Kleinunternehmer*in im Sinne von §19 Abs. 1 Umsatzsteuergesetz (UStG) wird keine Umsatzsteuer berechnet.
table_headline: 'Für die Bestellung fallen folgende Posten an:'
tax_excluded: exkl. MwSt.
tax_included: zzgl. Gesamtsumme MwSt. %{tax}%
tax_number: 'Steuernummer: %{number}'
title: Rechnung für die Bestellung bei %{supplier}
vat_exempt_rows:
- Name
- Anzahl
- Einzelpreis
- Artikel Gesamtpreis
no_price_markup_rows:
- Name
- Anzahl
- Einzelpreis (netto)
- Artikel Gesamtpreis (netto)
- MwSt.
- Artikel Gesamtpreis (brutto)
price_markup_rows:
- Name
- Anzahl
- Einzelpreis (netto)
- Artikel Gesamtpreis (netto)
- MwSt.
- Artikel Gesamtpreis (brutto) inkl. Foodcoopmarge %{marge}%
order_by_articles:
filename: Bestellung %{name}-%{date} - Artikelsortierung
title: 'Artikelsortierung der Bestellung: %{name}, beendet am %{date}'
@ -767,6 +833,7 @@ de:
heading: Artikelübersicht (%{count})
title: 'Sortiermatrix der Bestellung: %{name}, beendet am %{date}'
errors:
check_tax_number: Überprüft, ob die Steuernummer der Foodcoop richtig gesetzt ist
general: Ein Problem ist aufgetreten.
general_again: Ein Fehler ist aufgetreten. Bitte erneut versuchen.
general_msg: 'Ein Fehler ist aufgetreten: %{msg}'
@ -790,6 +857,8 @@ de:
close:
alert: 'Ein Fehler ist beim Abrechnen aufgetreten: %{message}'
notice: Bestellung wurde erfolgreich abgerechnet, die Kontostände aktualisiert.
notice_mail: Bestellung wurde erfolgreich abgerechnet, die Kontostände aktualisiert. Außerdem wurden automatisch Rechnungen an die Bestellgruppenmitglieder geschickt.
settings_not_set: Keine Emails mit Bestellgruppenrechnungen versendet. Bitte überprüfe die Einstellungen. Steuernummer gesetzt?
close_all_direct_with_invoice:
notice: 'Es wurden %{count} Bestellung abgerechnet.'
close_direct:
@ -854,11 +923,15 @@ de:
ended: beendet
name: Lieferantin
no_closed_orders: Derzeit gibt es keine beendeten Bestellungen.
state: Status
summary:
changed: Daten wurden verändert!
duration: von %{starts} bis %{ends}
fc_amount: 'FC-Betrag:'
deposit: 'Pfand netto:'
gross_deposit: 'Pfand brutto:'
fc_deposit: 'Pfand FC-Betrag:'
fc_profit: FC Gewinn
gross_amount: 'Bruttobetrag:'
groups_amount: 'Gruppenbeträge:'
@ -1132,6 +1205,7 @@ de:
create: Einladung verschicken
tasks:
required_users: "Es fehlen %{count} Mitstreiterinnen!"
task_title: "%{name} (%{duration}h)"
home:
apple_bar:
desc: 'Abgebildet ist das Verhältnis von erledigten Aufgaben zu dem Bestellvolumen Deiner Bestellgruppe im Vergleich zum Durchschnitt in der Foodcoop. Konkret: Pro %{amount} Bestellsumme solltest Du eine Aufgabe machen!'
@ -1231,6 +1305,7 @@ de:
header:
feedback:
desc: Fehler gefunden? Vorschlag? Idee? Kritik?
title: Feedback
help: Hilfe
logout: Abmelden
ordergroup: Meine Bestellgruppe
@ -1268,6 +1343,16 @@ de:
feedback:
header: "%{user} schrieb am %{date}:"
subject: Feedback zur Foodsoft
from_via_foodsoft: "%{name} via Foodsoft"
group_order_invoice:
subject: Bestellgruppenrechnung für %{group} bei %{supplier}
text: |
Liebe Bestellgruppe %{group},
Die Sammelbestellung bei %{supplier} wurde soeben abgerechnet und für die jeweiligen Bestellgruppen Rechnungen angelegt.
Im Anhang befindet sich daher eure Rechnung.
Viele Grüße von %{foodcoop}
invite:
subject: Einladung in die Foodcoop
text: |
@ -1423,6 +1508,7 @@ de:
stock: Lager
suppliers: Lieferanten/Artikel
title: Artikel
dashboard: Übersichtsseite
finances:
accounts: Konten verwalten
balancing: Bestellungen abrechnen
@ -1430,6 +1516,7 @@ de:
home: Übersicht
invoices: Rechnungen
title: Finanzen
foodcoop: Foodcoop
members: Mitglieder
ordergroups: Bestellgruppen
orders:
@ -1480,6 +1567,7 @@ de:
articles: Artikel
delivery_day: Liefertag
heading: Bestellung für %{name}
name: Name
number: Nummer
to_address: Versandaddresse
finish:
@ -1500,6 +1588,7 @@ de:
orders_finished: Beendet
orders_open: Laufend
orders_settled: Abgerechnet
not_closed: Bestellung noch nicht abgerechnet
title: Bestellungen verwalten
model:
close_direct_message: Die Bestellung wurde abgechlossen, ohne die Mitgliederkonten zu belasten.
@ -1579,6 +1668,7 @@ de:
index:
article_pdf: Artikel PDF
group_pdf: Gruppen PDF
matrix_pdf: Matrix PDF
title: Abholtage
sessions:
logged_in: Angemeldet!
@ -1589,6 +1679,7 @@ de:
forgot_password: Passwort vergessen?
login: Anmelden
nojs: Achtung, Cookies und Javascript müssen aktiviert sein! %{link} bitte abschalten.
noscript: NoScript
title: Foodsoft anmelden
shared:
articles:
@ -1617,8 +1708,13 @@ de:
who_ordered: Wer hat bestellt?
order_download_button:
article_pdf: Artikel PDF
download_file: Datei herunterladen
fax_csv: Fax CSV
fax_pdf: Fax PDF
fax_txt: Fax Text
group_pdf: Gruppen PDF
matrix_pdf: Matrix PDF
title: Herunterladen
task_list:
accept_task: Aufgabe übernehmen
done: Erledigt
@ -1675,10 +1771,11 @@ de:
profile:
language:
de: Deutsch
en: Englisch
es: Spanisch
tr: Türkisch
fr: Französisch
nl: Niederländisch
tr: Türkisch
required:
mark: "*"
text: benötigt
@ -1835,6 +1932,7 @@ de:
confirm_delete_single_from_group: Bist Du sicher, dass Du diese Aufgabe löschen möchtest (und in Bezug stehende wiederkehrende Aufgabe behalten möchtest)?
delete_group: Aufgabe und folgende löschen
edit_group: Wiederkehrende ändern
hours: "%{count}h"
mark_done: Als erledigt markieren
reject_task: Aufgabe ablehnen
title: Aufgabe anzeigen
@ -1861,6 +1959,9 @@ de:
delete: Löschen
download: Herunterladen
edit: Bearbeiten
marks:
close: "&times;"
success: <i class="icon icon-ok"></i>
move: Verschieben
or_cancel: oder abbrechen
please_wait: Bitte warten...
@ -1870,6 +1971,10 @@ de:
show: Anzeigen
views:
pagination:
first: "&laquo;"
last: "&raquo;"
next: "&rsaquo;"
previous: "&lsaquo;"
truncate: "..."
workgroups:
edit:
@ -1883,3 +1988,4 @@ de:
time:
formats:
foodsoft_datetime: "%d.%m.%Y %H:%M"
file: "%Y-%d-%B"

View file

@ -90,6 +90,18 @@ en:
tolerance: Tolerance
total_price: Sum
unit_price: Price/Unit
group_order_invoice:
name: Group order invoice
links:
delete: delete invoice
download: download invoice
invoice_date: date of group order invoice
generate: generate invoice
generate_with_date: set & generate
download_all_zip: download all invoices as zip
payment_method: Credit
tax_number_not_set: Tax number not set in configs
invoice:
amount: Amount
attachment: Attachment
@ -158,6 +170,7 @@ en:
contact_address: Address
contact_person: Contact person
contact_phone: Phone
customer_number: Customer number
description: Description
ignore_apple_restriction: Ignore order stop by apple points restriction
last_order: Last order
@ -318,6 +331,7 @@ en:
emails_title: Sending email
tab_payment:
schedule_title: Ordering schedule
group_order_invoices: Group order invoices
tab_security:
default_roles_title: Access to
default_roles_paragraph: By default every member of the foodcoop has access to the following areas.
@ -603,6 +617,9 @@ en:
email_from: Emails will appear to be from this email address. Leave empty to use the foodcoop's contact address.
email_replyto: Set this when you want to receive replies from emails sent by Foodsoft on a different address than the above.
email_sender: Emails will appear to be sent from this email address. To avoid emails sent being classified as spam, the webserver may need to be registered in the SPF record of the email address's domain.
use_automatic_invoices: A listing of the invoice items is made without explicit display of VAT and the invoice receives the necessary addition regarding the small business regulation §19 (applies to Germany)
payment_method: Payment type is declared on the order group invoice
vat_exempt: A listing of the invoice items is made without explicit display of VAT and the invoice contains the necessary addition regarding the German Kleinunternehmerregelung §19 UStG (attention! FoodCoop marge not included in nvoice).
help_url: Documentation website.
homepage: Website of your foodcoop.
ignore_browser_locale: Ignore the language of user's computer when the user has not chosen a language yet.
@ -630,6 +647,8 @@ en:
tolerance_is_costly: Order as much of the member tolerance as possible (compared to only as much needed to fill the last box). Enabling this also includes the tolerance in the total price of the open member order.
distribution_strategy: How articles should be distributed after an order has been received.
use_apple_points: When the apple point system is enabled, members are required to do some tasks to be able to keep ordering.
use_automatic_invoices: When an order is settled, invoices for the individual order groups are automatically sent by mail
payment_method: Payment Method for group order invoices
use_boxfill: When enabled, near end of an order, members are only able to change their order when increases the total amount ordered. This helps to fill any remaining boxes. You still need to set a box-fill date for the orders.
use_iban: When enabled, supplier and user provide an additonal field for storing the international bank account number.
use_nick: Show and use nicknames instead of real names. When enabling this, please check that each user has a nickname.
@ -645,6 +664,7 @@ en:
phone: Phone
street: Street
zip_code: Postcode
tax_number: Tax number
currency_space: add space
currency_unit: Currency
custom_css: Custom CSS
@ -689,6 +709,11 @@ en:
first_order_first_serve: First distribute to those who ordered first
no_automatic_distribution: No automatic distribution
use_apple_points: Apple points
group_order_invoices:
use_automatic_invoices: Send automatically via mail after oder settlement
payment_method: Payment method
separate_deposits: Separate deposits on invoice
vat_exempt: This foodcoopis VAT exempt
use_boxfill: Box-fill phase
use_iban: Use IBAN
use_nick: Use nicknames
@ -746,6 +771,47 @@ en:
update:
notice: Delivery was updated.
documents:
group_order_invoice_pdf:
ordergroup:
contact_phone: 'Phone: %{contact_phone}'
contact_address: 'Adress : %{contact_address}'
customer_number: 'Customer number: %{customer_number}'
name: 'Ordergroup: %{ordergroup}'
filename: Invoice%{number}
invoicee: Invoicee
invoicer: Invoicer
invoice_date: 'Invoice date: %{invoice_date}'
invoice_number: 'Invoice number: %{invoice_number}'
markup_included: incl Foodcoop Marge on gross price %{marge}%
payment_method: 'Payment_method: %{payment_method}'
small_business_regulation: As a small entrepreneur in the sense of §19 para. 1 of the Umsatzsteuergesetz (UStG), no value added tax is charged.
sum_to_pay: Total sum
sum_to_pay_net: Total sum (net)
sum_to_pay_gross: Total sum (gross)
table_headline: 'The following items will be charged for the order:'
tax_excluded: excl. MwSt.
tax_included: incl. VAT %{tax}%
tax_number: 'Tax number: %{number}'
title: Invoice for order at %{supplier}
vat_exempt_rows:
- Name
- Quantity
- Unit price
- Total price
no_price_markup_rows:
- Name
- Quantity
- Unit price (net)
- Total price (net)
- VAT
- Total price (gross)
price_markup_rows:
- Name
- Quantity
- Unit price (net)
- Total price (net)
- VAT
- Total price (gross) incl. foodcoop margin
order_by_articles:
filename: Order %{name}-%{date} - by articles
title: 'Order sorted by articles: %{name}, closed at %{date}'
@ -769,6 +835,7 @@ en:
heading: Article overview (%{count})
title: 'Order sorting matrix: %{name}, closed at %{date}'
errors:
check_tax_number: Please check whether the foodcoop's tax number is set correctly.
general: A problem has occured.
general_again: A problem has occured. Please try again.
general_msg: 'A problem has occured: %{msg}'
@ -792,6 +859,7 @@ en:
close:
alert: 'An error occured while accounting: %{message}'
notice: Order was settled succesfully, the balance of the account was updated.
settings_not_set: No emails with order group invoices sent. Please check the settings. Tax number set?
close_all_direct_with_invoice:
notice: '%{count} orders have been settled.'
close_direct:
@ -1272,6 +1340,15 @@ en:
feedback:
header: "%{user} wrote at %{date}:"
subject: Feedback for Foodsoft
group_order_invoice:
subject: Order group invoice for %{group} at %{supplier}
text: |
Dear order group %{group},
The collective order at %{supplier} has just been settled and invoices have been created for the respective order groups.
Attached you will find your invoice.
Best regards from %{foodcoop}
from_via_foodsoft: "%{name} via Foodsoft"
invite:
subject: Invitation to the Foodcoop
@ -1511,6 +1588,7 @@ en:
orders_finished: Closed
orders_open: Open
orders_settled: Settled
not_closed: Order not yet settled
title: Manage orders
model:
close_direct_message: Order settled without charging member accounts.
@ -1910,3 +1988,4 @@ en:
time:
formats:
foodsoft_datetime: "%Y-%m-%d %H:%M"
file: "%Y-%d-%B"

View file

@ -35,9 +35,15 @@ es:
unit_quantity: Cantidad de unidades
bank_account:
balance: Saldo
bank_gateway: Pasarela bancaria
description: Descripción
iban: IBAN
name: Nombre
bank_gateway:
authorization: Cabecera-Autorización
name: Nombre
unattended_user: Usuario desatendido
url: Enlace
bank_transaction:
amount: Cantidad
date: Fecha
@ -65,6 +71,7 @@ es:
ordergroup: Grupo de pedido
user: Ingresado por
financial_transaction_class:
ignore_for_account_balance: Ignorar en el saldo de la cuenta
name: Nombre
financial_transaction_type:
bank_account: Cuenta bancaria
@ -186,6 +193,11 @@ es:
phone2: teléfono 2
shared_sync_method: Cómo sincronizar
url: Web
supplier_category:
name: Nombre
description: Descripción
financial_transaction_class: Clase de transacciones financieras
bank_account: Cuenta bancaria
task:
created_by: Creado por
created_on: Creado en
@ -243,6 +255,8 @@ es:
models:
article: Artículo
article_category: Categoría
bank_account: Cuenta bancaria
bank_gateway: Pasarela bancaria
bank_transaction: Transacción bancaria
delivery: Entrega
financial_transaction: Transacción financiara
@ -258,6 +272,7 @@ es:
stock_article: Artículo de stock
stock_taking: Toma de inventario
supplier: Proveedor
supplier_category: Categoría del proveedor
task: Tarea
user: Usuario
workgroup: Grupo de trabajo
@ -268,7 +283,7 @@ es:
all_ordergroups: Todos los grupos de pedido
all_users: Todos los usuarios
all_workgroups: Todos los grupos de trabajo
created_at: creado
created_at: creado
first_paragraph: Aquí puedes administrar grupos y usuarios de Foodsoft.
groupname: nombre del grupo
members: miembros
@ -281,6 +296,14 @@ es:
title: Administración
type: tipo
username: nombre de usuario
bank_accounts:
form:
title_edit: Editar cuenta bancaria
title_new: Añadir nueva cuenta bancaria
bank_gateways:
form:
title_edit: Editar pasarela bancaria
title_new: Añadir nueva pasarela bancaria
configs:
list:
key: Clave
@ -308,6 +331,26 @@ es:
finances:
index:
bank_accounts: Cuentas bancarias
first_paragraph: Aquí puede administrar las clases de transacciones financieras y los tipos de transacciones financieras correspondientes. Cada transacción financiera tiene un tipo, que usted tiene que seleccionar en cada transacción, si usted creó más de un tipo. Las clases de transacciones financieras pueden utilizarse para agrupar los tipos de transacciones financieras y se mostrarán como columnas adicionales en el resumen de la cuenta, si se ha creado más de una.
new_bank_account: Añadir nueva cuenta bancaria
new_financial_transaction_class: Añadir nueva clase de transacción financiera
new_bank_gateway: Añadir nueva pasarela bancaria
title: Finanzas
transaction_types: Tipos de transacciones financieras
supplier_categories: Categorías de proveedores
new_supplier_category: Nueva categoría de proveedor
transaction_types:
name: Nombre
new_financial_transaction_type: Añadir nuevo tipo de transacción financiera
financial_transaction_classes:
form:
title_edit: Editar clase de transacción financiera
title_new: Añadir nueva clase de transacción financiera
financial_transaction_types:
form:
name_short_desc: El nombre corto es obligatorio para los tipos de transacciones financieras que deben ser asignados automáticamente en las transacciones bancarias. Si hay varias cuentas bancarias, se puede seleccionar la cuenta preferida para las transferencias bancarias.
title_edit: Editar tipo de transacción financiera
title_new: Añadir nuevo tipo de transacción financiera
mail_delivery_status:
destroy_all:
notice: Se han borrado todos los problemas de email
@ -345,11 +388,15 @@ es:
notice: El usuario/a ha sido borrado
edit:
title: Edita usuario/a
form:
create_ordergroup: Crear grupo de pedido con el mismo nombre y añadir usuario.
send_welcome_mail: Enviar un correo de bienvenida al usuario/a.
index:
first_paragraph: Aquí puedes %{url}, editar y borar usuarios.
new_user: Crea nuevo usuario/a
new_users: crea nuevo
show_deleted: Muestra usuarios borrados
title: Usuario/a administrador
new:
title: Crea nuevo usuario
restore:
@ -390,6 +437,10 @@ es:
workgroups:
members: miembros
name: nombre
supplier_categories:
form:
title_new: Añadir categoría de proveedor
title_edit: Editar categoría de proveedor
application:
controller:
error_authn: Es necesaria la autenticación!
@ -397,6 +448,7 @@ es:
error_denied_sign_in: entra como otro usuario/a
error_feature_disabled: Esta opción está actualmente deshabilitada
error_members_only: Esta acción está sólo disponible para miembros de un grupo.
error_minimum_balance: Lo sentimos, el saldo de tu cuenta está por debajo del mínimo de %{min}.
error_token: Acceso denegado (invalid token).
article_categories:
create:
@ -433,6 +485,7 @@ es:
error_update: 'Ha ocurrido un error miebtras se actualizaba el artículo ''%{article}'': %{msg}'
parse_upload:
no_file: Elige un archivo para subir.
notice: "%{count} artículos fueron analizados con éxito."
sync:
notice: El catálogo está actualizado
shared_alert: "%{supplier} no está conectado a una base de datos externa"
@ -462,6 +515,7 @@ es:
not_found: No se han encontrado articulos
index:
change_supplier: Cambiar proveedor ...
download: Descargar artículos
edit_all: Editar todos
ext_db:
import: Importar artículo
@ -513,18 +567,29 @@ es:
status: Estado (x=saltar)
file_label: Por favor elige un archivo compatible
options:
convert_units: Mantener unidades actuales, recomputar la cantidad y precio de unidades (como sincronizar).
convert_units: Mantener unidades actuales, recomputar la cantidad y precio de unidades (como sincronizar).
outlist_absent: Borrar artículos que no están en el archivo subido.
sample:
juices: Jugos
nuts: Nueces
organic: Orgánico
supplier_1: Nuttyfarm
supplier_2: Brownfields
supplier_3: Greenfields
tomato_juice: Jugo de tomate
walnuts: Nogal
submit: Subir archivo
text_1: 'Aquí puedes subir una hoja de cálculo para actualizar los artículos de %{supplier}. Se aceptan los formatos Excel (xls, xlsx) y OpenOffice (ods), al igual que archivos CSV (con columnas separadas por ";" con codificación UTF-8). Solo se importará la primera hoja y las columnas deben estar en el siguiente orden:'
text_2: Las hileras que se muestran aquí son ejemplos. Cuando hay una "x" en la primera columna, el artículo se sacará de la lista. Esto te permite editar la hoja de cálculo y rápidamente sacar muchos artículos a la vez, por ejemplo cuando los artículos ya no están disponibles con el proveedor. La categoría se hará coincidir con tu lista de categorías de Foodsoft (tanto por nombre de categoría como nombre de importación).
title: Subir artículos de %{supplier}
bank_account_connector:
confirm: Por favor, confirme el código %{code}.
fields:
email: E-Mail
pin: PIN
password: Contraseña
tan: TAN
username: Nombre de Usuario/a
config:
hints:
applepear_url: Web donde se explica el sistema de manzanas y peras.
@ -546,7 +611,9 @@ es:
order_schedule:
boxfill:
recurr: Programa cuándo la fase de llenado de cajas comienza por defecto.
time: Tiempo por defecto cuando comienza la fase de llenado de caja del pedido.
ends:
recurr: Programa para la fecha predeterminada de cierre de pedidos.
time: Fecha por defecto cuando se cierran los pedidos.
initial: La agenda comienza en esta fecha.
page_footer: Se muestra en cada página en la parte inferior. Dejar vacío para desactivar el pie de página por completo.
@ -566,12 +633,15 @@ es:
use_boxfill: Cuando está activado, cerca del cierre de un pedido los miembros no podrán cambiar su pedido a menos que se incremente el valor pedido total. Esto ayudará a llenar las cajas que faltan. Igualmente deberás decidir una fecha de llenado de cajas para los pedidos.
use_iban: Cuando esta opción está habilitada, el proveedor y el usuario pueden guardan también su número de cuenta bancaria internacional (IBAN).
use_nick: Muestra y utiliza apodos en lugar de nombres reales. Cuando activas esto debes chequear que todos los usuarios tengan apodo.
use_self_service: Cuando está activado, los miembros pueden usar las funciones de balance seleccionadas por sí mismos.
webstats_tracking_code: Código de seguimiento para analíticas web (como Piwik o Google analytics). Dejar en blanco si no usa estas analíticas.
keys:
applepear_url: Enlace de ayuda para el sistema de puntos-manzana
charge_members_manually: Cambia los miembros manualmente
contact:
city: Ciudad
country: País
email: E-mail
phone: Teléfono
street: Calle
zip_code: Código postal
@ -579,6 +649,12 @@ es:
currency_unit: Moneda
custom_css: CSS adicional
default_locale: Idioma por defecto
default_role_article_meta: Artículos
default_role_finance: Finanzas
default_role_invoices: Facturas
default_role_orders: Pedidos
default_role_pickups: Días de recogida
default_role_suppliers: Proveedores
disable_invite: Desactivar invitaciones
disable_members_overview: Desactivar la lista de miembros
email_from: Dirección de email de origen
@ -604,6 +680,7 @@ es:
price_markup: Margen de la cooperativa
stop_ordering_under: Puntos-manzana mínimos
tasks_period_days: Periodo
tasks_upfront_days: Crear de antemano
tax_default: IVA por defecto
time_zone: Zona horaria
tolerance_is_costly: La tolerancia es prioritaria
@ -615,8 +692,10 @@ es:
use_boxfill: Fase de llenar las cajas
use_iban: Usar IBAN
use_nick: Usa apodos
use_self_service: Usar auto servicio
webstats_tracking_code: Código de seguimiento
tabs:
applications: Aplicaciones
foodcoop: Cooperativa
language: Idioma
layout: Disposición
@ -624,6 +703,7 @@ es:
messages: Mensajes
others: Otro
payment: Finanzas
security: Seguridad
tasks: Tareas
deliveries:
add_stock_change:
@ -683,9 +763,11 @@ es:
- Unidad
- Precio/Unidad
- Subtotal
total: Total
order_matrix:
filename: Pedido %{name}-%{date} - matrix para ordenar
heading: Descripción del artículo (%{count})
title: 'Matriz de ordenamiento de pedidos: %{name}, cerrada a las %{date}'
errors:
general: Ha ocurrido un problema.
general_again: Ha ocurrido un problema. Por favor inténtalo de nuevo.
@ -702,6 +784,7 @@ es:
notice: Tus comentarios fueron enviados con éxito. ¡Muchas gracias!
new:
first_paragraph: '¿Encontraste un error? ¿Tienes sugerencias, ideas o comentarios? Nos gustaría recibir tus comentarios.'
second_paragraph: Tenga en cuenta que el equipo de Foodsoft es el único responsable del mantenimiento del software. Para preguntas relacionadas con la organización de tu Foodcoop, por favor contacta a la persona de contacto apropiada.
send: Enviar
title: Enviar comentarios
finance:
@ -709,6 +792,8 @@ es:
close:
alert: 'Ocurrió un error en la contabilidad: %{message}'
notice: El pedido se ha cerrado con éxito, el balance de la cuenta ha sido actualizado.
close_all_direct_with_invoice:
notice: '%{count} pedidos han sido liquidados.'
close_direct:
alert: 'El pedido no se puede cerrar: %{message}'
notice: El pedido ha sido cerrado
@ -717,17 +802,23 @@ es:
first_paragraph: 'Cuando el pedido se cierre se actualizarán todas las cuentas del grupo. <br />Las cuentas serán cargadas así:'
or_cancel: o vuelve a contabilidad
title: Cierra el pedido
edit_note:
title: Editar nota de pedido
edit_results_by_articles:
add_article: Añadir artículo
amount: Importe
edit_transport: Editar transporte
gross: Bruto
net: Neto
edit_transport:
title: Distribuir costes de transporte
group_order_articles:
add_group: Añadir grupo
total: Costes totales
total_fc: Suma (precio al grupo)
units: Unidades
index:
close_all_direct_with_invoice: Cerrar todo con factura
title: Pedidos cerrados
invoice:
edit: Editar factura
@ -778,7 +869,10 @@ es:
with_extra_charge: 'con cargo extra:'
without_extra_charge: 'sin cargo extra:'
bank_accounts:
assign_unlinked_transactions:
notice: '%{count} transacciones han sido asignadas'
import:
notice: '%{count} nuevas transacciones han sido importadas'
no_import_method: Para esta cuenta bancaria no se ha configurado ningún método de importación.
submit: Importar
title: Importar transacciones bancarias para %{name}
@ -807,12 +901,16 @@ es:
notice: El enlace a la factura ha sido añadido.
create:
notice: Se ha creado un nuevo enlance financiero.
create_financial_transaction:
notice: La transacción financiera ha sido añadida.
index_bank_transaction:
title: Añadir transacción bancaria
index_financial_transaction:
title: Añadir transacción financiera
index_invoice:
title: Añadir factura
new_financial_transaction:
title: Añadir transacción financiera
remove_bank_transaction:
notice: Se ha eliminado el enlace a la transacción bancaria.
remove_financial_transaction:
@ -820,7 +918,15 @@ es:
remove_invoice:
notice: El enlace a la factura ha sido eliminado.
show:
add_bank_transaction: Añadir transacción bancaria
add_financial_transaction: Añadir transacción financiera
add_invoice: Añade factura
amount: Cantidad
date: Fecha
description: Descripción
new_financial_transaction: Nueva transacción financiera
title: Enlace financiero %{number}
type: Tipo
financial_transactions:
controller:
create:
@ -829,7 +935,11 @@ es:
alert: 'Ha ocurrido un error: %{error}'
error_note_required: Note se requiere!
notice: Se han guardado todas las transacciones
destroy:
notice: La transacción ha sido eliminada.
index:
balance: 'Saldo de la cuenta: %{balance}'
last_updated_at: "(última actualización hace %{when})"
new_transaction: Crea nueva transacción
title: Balance de cuentas para %{name}
index_collection:
@ -837,16 +947,26 @@ es:
title: Transacciones financieras
new:
paragraph: Aquí puedes poner o quitar dinero del grupo de pedido <b>%{name}</b>.
paragraph_foodcoop: Aquí puedes poner y quitar dinero para el <b>foodcoop</b>.
title: Nueva transacción
new_collection:
add_all_ordergroups: Añade todos los grupos de pedido
add_all_ordergroups_custom_field: Añadir todos los pedidos de grupo con %{label}
create_financial_link: Crear un vínculo financiero común para las nuevas transacciones.
create_foodcoop_transaction: Crear una transacción con la suma inversa para el foodcoop (en el caso de "doble entrada de cuenta")
new_ordergroup: Añade nuevo grupo de pedido
save: Guarda transacción
set_balance: Ajuste el saldo del grupo de pedido a la cantidad introducida.
sidebar: Aquí puedes actualizar más cuentas al mismo tiempo. Por ejemplo, todas las transferencias del grupo de pedido de un balance de cuenta.
title: Actualizar más cuentas
ordergroup:
remove: Remover
remove_group: Remover grupo
transactions:
confirm_revert: '¿Estás seguro de que quieres revertir %{name}? En este caso se creará una nueva transacción con una cantidad invertida y en combinación con la transacción original ocultada. Estas transacciones ocultas sólo son visibles a través de la opción ''Mostrar oculto'' y no son visibles para los usuarios normales en absoluto.'
revert_title: Revertir la transacción, que la ocultará a los usuarios normales.
transactions_search:
show_hidden: Mostrar transacciones ocultas
index:
amount_fc: Importe(FC)
end: Fin
@ -863,6 +983,7 @@ es:
attachment_hint: Sólo se permiten los formatos JPEG y PDF.
index:
action_new: Crea nueva factura
show_unpaid: Mostrar facturas no pagadas
title: Facturas
new:
title: Crea nueva factura
@ -874,8 +995,10 @@ es:
title: Facturas impagas
ordergroups:
index:
new_financial_link: Nuevo enlace financiero
new_transaction: Añade nuevas transacciones
show_all: Todas las transacciones
show_foodcoop: Transacciones de Foodcoop
title: Maneja los grupos
ordergroups:
account_statement: Balance de cuenta
@ -889,6 +1012,8 @@ es:
only_active: Sólo grupos activos
only_active_desc: "(han hecho al menos un pedido en los últimos 3 meses)"
title: Grupo de pedido
ordergroups:
break: "%{start} - %{end}"
users:
index:
body: "<p>Desde aquí puedes escribir un mensaje a los miembros de tu cooperativa Foodcoop. Recuerda habilitar en %{profile_link} tus detalles de contacto para que sean visibles.</p>"
@ -987,10 +1112,12 @@ es:
application:
edit_user: Edita usuario
nick_fallback: "(no tiene apodo)"
role_admin: Admin
role_article_meta: Artículos
role_finance: Finanzas
role_invoices: Facturas
role_orders: Pedidos
role_pickups: Días de recogida
role_suppliers: Proveedores
show_google_maps: Muéstralo en Google maps
sort_by: Ordena por %{text}
@ -1000,12 +1127,14 @@ es:
orders:
old_price: Precio anterior
option_choose: Elige proveedor/stock
option_stock: Existencias
order_pdf: Crea PDF
submit:
invite:
create: envía invitación
tasks:
required_users: "Aún se necesitan %{count} miembros!"
task_title: "%{name} (%{duration}h)"
home:
apple_bar:
desc: 'Esto muestra la proporción de tareas completadas respecto al volumen de pedidos de tu grupo de pedido en comparación con el promedio en Foodcoop. En práctica: por cada %{amount} de pedidos totales, tú deberías hacer una tarea!'
@ -1014,8 +1143,9 @@ es:
warning: Cuidado, si tienes menos de %{threshold} puntos-manzana no puedes hacer un pedido!
changes_saved: Guarda los cambios.
index:
due_date_format: "%A %d %B"
my_ordergroup:
last_update: La última actualización fue hace %{when}
last_update: La última actualización fue hace %{when}
title: Mi grupo de pedido
transactions:
title: Últimas transacciones
@ -1047,12 +1177,21 @@ es:
title: Mi Perfil
user:
since: "(miembro para %{when})"
title: "%{user}"
reference_calculator:
transaction_types_headline: Propósito
placeholder: Por favor, introduzca primero las cantidades que desea transferir en cada campo, para ver la referencia que debe utilizar para esa transacción.
text0: Por favor transfiera
text1: con la referencia
text2: a la cuenta bancaria
title: Calculador de referencia
start_nav:
admin: Administración
finances:
accounts: Actualizar cuentas
settle: Pedidos de la cuenta
title: Finanzas
foodcoop: Foodcoop
members: Miembros
new_ordergroup: Nuevo grupo de pedido
new_user: Nuevo miembro
@ -1081,20 +1220,30 @@ es:
ordering:
confirm_change: Las modificaciones sobre este pedido se perderán cuando cambies el pedido. ¿Quieres perder los cambios que has hecho y continuar?
trix_editor:
file_size_alert: ¡El archivo adjunto es demasiado grande! El tamaño máximo es de 512Mb
file_size_alert: '¡El archivo adjunto es demasiado grande! El tamaño máximo es de 512Mb'
layouts:
email:
footer_1_separator: "--"
footer_2_foodsoft: 'Foodsoft: %{url}'
footer_3_homepage: 'Foodcoop: %{url}'
footer_4_help: 'Ayuda: %{url}'
help: 'Ayuda'
foodsoft: Foodsoft
footer:
revision: revisión %{revision}
header:
feedback:
desc: '¿Encontrase algún error? ¿Sugerencias? ¿Ideas?'
title: Sugerencias
help: Ayuda
logout: Salir
ordergroup: Mis grupos de pedido
profile: Edita perfil
reference_calculator: Calculador de referencia
logo: "<span>food</span>soft"
lib:
render_pdf:
page: Página %{number} de %{count}
login:
accept_invitation:
body: "<p>Has sido invitado a formar parte de %{foodcoop} como miembro del grupo <b>%{group}</b>.</p> <p>Si quieres participar, es necesario que completes este formulario.</p> <p>Tu información no será compartida con terceros bajo ninguna razón. Puedes decidir qué información personal será visible. 'Todos' hace referencia a todos los miembros de Foodcoop. Sólo los administradores tienen acceso a tu información.</p>"
@ -1107,7 +1256,7 @@ es:
error_invite_invalid: Tu invitación no es válida.
error_token_invalid: La sesión ha expirado o no es válida. Prueba de nuevo.
reset_password:
notice: Si tu email está ya registrado aquí, recibirás un mensaje con un enlace para
notice: Si tu email está ya registrado aquí, recibirás un mensaje con un enlace para
update_password:
notice: Tu contraseña ha sido actualizada. Prueba a conectarte ahora.
forgot_password:
@ -1119,9 +1268,13 @@ es:
submit: Guardar la nueva contraseña
title: Nueva contraseña
mailer:
dateformat: "%d %b"
feedback:
header: "%{user} escribió %{date}:"
subject: Comentarios para Foodsoft
from_via_foodsoft: "%{name} vía Foodsoft"
invite:
subject: Invitación al Foodcoop
text: |
Hola!
@ -1164,6 +1317,8 @@ es:
Queridos miebros de %{ordergroup},
El pedido de "%{order}" ha sido cerrado por %{user} en %{when}.
text1: |
Puede ser posiblemente recogido en %{pickup}.
text2: |
Los siguientes artículos se han pedido para tu grupo de pedido:
text3: |-
@ -1173,6 +1328,18 @@ es:
Abrazos %{foodcoop}.
order_received:
subject: 'Envío de pedido registrado: %{name}'
text0: |
Estimado %{ordergroup},
el pedido de "%{order}" ha sido recibido.
abundant_articles: Recibido demasiado
scarce_articles: Recibido muy poco
article_details: |
o %{name}:
-- Solicitado: %{ordered} x %{unit}
-- Recibido: %{received} x %{unit}
order_result_supplier:
subject: Nuevo pedido para %{name}
text: |
@ -1187,6 +1354,16 @@ es:
%{foodcoop}
reset_password:
subject: Hay tareas que se deben hacer ya!
text: |
Hola %{user},
Has (o alguien más) solicitado una nueva contraseña.
Para elegir una nueva contraseña, siga este enlace: %{link}
Este enlace funciona sólo una vez y expira el %{expires}.
Si no quieres cambiar tu contraseña, simplemente ignora este mensaje. Tu contraseña no ha sido cambiada aún.
¡Saludos, tu equipo de Foodsoft!
upcoming_tasks:
nextweek: 'Tareas para la semana que viene:'
subject: Tareas que hay que hacer ya!
@ -1199,16 +1376,50 @@ es:
Saludos de %{foodcoop}.
welcome:
subject: Bienvenido al Foodcoop
text0: |
Estimado %{user},
se ha creado una nueva cuenta Foodsoft para ti.
text1: |
Para elegir una nueva contraseña, siga este enlace: %{link}
Este enlace solo funciona una vez y caduca el %{expires}.
Siempre puedes usar "¿Olvidaste la contraseña?" para obtener un nuevo enlace.
Saludos de %{foodcoop}.
messages_mailer:
foodsoft_message:
footer: |
Respuesta: %{reply_url}
Ver mensaje en línea: %{msg_url}
Opciones de mensaje: %{profile_url}
footer_group: |
Enviado al grupo: %{group}
model:
delivery:
each_stock_article_must_be_unique: Los artículos de stock no pueden ser listados más de una vez.
financial_transaction:
foodcoop_name: Foodcoop
financial_transaction_type:
no_delete_last: Debe existir al menos un tipo de transacción financiera.
group_order:
stock_ordergroup_name: Existencias (%{user})
invoice:
invalid_mime: tiene un tipo de MIME inválido (%{mime})
membership:
no_admin_delete: No te puedes salir de este grupo porque eres el último adimistrador/a.
order_article:
error_price: debe especificarse y tener un precio actual
user:
no_ordergroup: no hay célula
group_order_article:
order_closed: El pedido está cerrado y no se puede modificar
navigation:
admin:
config: Configuración
finance: Finanzas
home: Resumen
mail_delivery_status: Problemas de email
ordergroups: Grupos de pedido
@ -1217,12 +1428,14 @@ es:
workgroups: grupos de trabajo
articles:
categories: Categorías
stock: Existencias
suppliers: Proveedores/artículos
title: Artículos
dashboard: Escritorio
finances:
accounts: Administrar cuentas
balancing: Pedidos de cuenta
bank_accounts: Cuentas bancarias
home: Resumen
invoices: Facturas
title: Finanzas
@ -1233,6 +1446,7 @@ es:
archive: Mis Pedidos
manage: Gestionar pedidos
ordering: Hacer pedido!
pickups: Días de recogida
title: Pedidos
tasks: Tareas
workgroups: Grupos de trabajo
@ -1270,6 +1484,7 @@ es:
field_unlocked_title: La distribución de este artículo entre los grupos de pedido se ha cambiado a mano. Cuando cambies las cantidades, esos cambios manuales se perderán.
edit_amounts:
no_articles_available: Ningún artículo para añadir.
set_all_to_zero: Poner todo a cero
fax:
amount: Cantidad
articles: Artículos
@ -1303,7 +1518,9 @@ es:
error_closed: El pedido ya estaba cerrado
error_nosel: Debes seleccionar al menos un artículo. Quizás quieres borrar el pedido?
error_starts_before_boxfill: tiene que ser después de la fecha de comienzo (o estar vacío)
error_starts_before_ends: debe ser después de la fecha de inicio (o permanecer vacío)
notice_close: 'Pedido: %{name}, hasta %{ends}'
stock: Existencias
warning_ordered: 'Cuidado: los artículos marcados en rojo ya han sido pedidos en este pedido abierto. Si los deseleccionas aquí, todos los pedidos actuales de estos artículos se borrarán. Para proceder, confirma abajo.'
warning_ordered_stock: 'Cuidado: Los artículos marcados en rojo ya han sido pedidos en este pedido de stock. Si los deseleccionas aquí, todos los pedidos y compras de estos artículos se borrarán y no estarán en la contabilidad. Para proceder, confirma abajo.'
new:
@ -1313,6 +1530,8 @@ es:
consider_member_tolerance: considera la tolerancia
notice: 'Pedido recibido: %{msg}'
notice_none: Ningún nuevo artículo para recibir
paragraph: Si el pedido y el importe recibido son los mismos, los campos correspondientes pueden estar vacíos. Sigue siendo buena práctica entrar en todos los campos, ya que esto proporciona una forma fácil de verificar que todos los artículos han sido seleccionados.
rest_to_stock: restablecer a valores en existencias
submit: recibe pedido
surplus_options: 'Opciones de distribución:'
title: Recibiendo %{order}
@ -1326,8 +1545,15 @@ es:
comments:
title: Comentarios
comments_link: Comentarios
confirm_delete: '¿Estás seguro/a de que quieres borrar el pedido?'
confirm_end: |-
¿Realmente desea cerrar el pedido %{order}?
No hay vuelta atrás.
confirm_send_to_supplier: El pedido ya ha sido enviado al proveedor el %{when}. ¿Realmente desea enviarlo de nuevo?
create_invoice: Añade factura
description1_order: "%{state} pedido de %{supplier} abierto por %{who}"
description1_period:
pickup: y puede ser recogido en %{pickup}
starts: abierto desde %{starts}
starts_ends: abierto desde %{starts} hasta %{ends}
description2: "%{ordergroups} ha pedido %{article_count} artículos, con un valor total de %{net_sum} / %{gross_sum} (neto / bruto)."
@ -1353,14 +1579,30 @@ es:
notice: Se actualizó el pedido.
update_order_amounts:
msg1: "%{count} artículos (%{units} units) actualizados"
msg2: "%{count} (%{units}) usando tolerancia"
msg4: "%{count} (%{units}) sobra"
pickups:
document:
empty_selection: Debe seleccionar al menos un pedido.
filename: Recogida para %{date}
invalid_document: Tipo de documento inválido
title: Recogida para %{date}
index:
article_pdf: Artículo PDF
group_pdf: Grupo PDF
matrix_pdf: Matrix PDF
title: Días de recogida
sessions:
logged_in: '¡Te has conectado!'
logged_out: '¡Te has desconectado!'
login_invalid_email: Dirección de email o contraseña no válidas
login_invalid_nick: Usuario o contraseña no válidos
new:
forgot_password: '¿Has olvidado la contraseña?'
login: Entra
nojs: Atención, las cookies y el javascript deben ser activados! Por favor desactiva %{link}.
noscript: NoScript
title: Inicio de sesión Foodsoft
shared:
articles:
ordered: Pedidos
@ -1389,6 +1631,11 @@ es:
order_download_button:
article_pdf: Artículos PDF
download_file: Descargar archivo
fax_csv: Fax CSV
fax_pdf: Fax PDF
fax_txt: Texto fax
group_pdf: Grupo PDF
matrix_pdf: Matrix PDF
title: Descargar
task_list:
accept_task: Acepta la tarea
@ -1404,9 +1651,13 @@ es:
workgroup_members:
title: Membresías de grupo
simple_form:
error_notification:
default_message: Se han encontrado errores. Por favor, compruebe el formulario.
hints:
article:
unit: por ej. KG o 1L o 500g
article_category:
description: lista separada por comas de nombres de categorías reconocidos en la importación/sincronización
order_article:
units_to_order: Si cambias la cantidad total de unidades enviadas también tendrás que cambiar los valores individuales de grupo haciendo click en el nombre del artículo. No serán recalculados automáticamente, así que a los otros grupos de pedido se les podrían ser cobrar artículos que no llegarán!
update_global_price: Actualizar el precio para futuros pedidos
@ -1426,6 +1677,7 @@ es:
notify:
negative_balance: Infórmame cuando mi grupo de pedido tenga un balance negativo.
order_finished: Infórmame acerca del resultado de mi pedido (cuando se cierre).
order_received: Infórmame sobre los datos de entrega (después de recibir el pedido).
upcoming_tasks: Recordarme las tareas incompletas.
profile:
email_is_public: El email es visible para otros miembros
@ -1435,6 +1687,7 @@ es:
settings_group:
messages: Mensajes
privacy: Privacidad
'no': 'No'
options:
settings:
profile:
@ -1446,6 +1699,7 @@ es:
nl: Neerlandés
tr: Turco
required:
mark: "*"
text: requerido
'yes': 'Sí'
stock_takings:
@ -1459,22 +1713,34 @@ es:
new:
amount: Cantidad
create: crea
stock_articles: Artículos en existencias
temp_inventory: inventario temporal
text_deviations: Por favor, rellene todas las desviaciones excedentes del %{inv_link}. Para la reducción, utilice un número negativo.
text_need_articles: Tienes que %{create_link} un nuevo artículo de existencias antes de poder usarlo aquí.
title: Crear nuevo inventario
show:
amount: Cantidad
article: Artículo
confirm_delete: '¿Realmente deseas eliminar el inventario?'
date: Fecha
note: Nota
overview: Inventario
supplier: Proveedor
title: Muestra inventario
unit: Unidad
stock_takings:
confirm_delete: '¿Estás seguro que quieres borrar esto?'
date: Fecha
note: Nota
update:
notice: Inventario actualizado.
stockit:
check:
not_empty: "%{name} no se pudo borrar, el inventario no es cero."
copy:
title: Copia artículo de stock
create:
notice: Se ha creado el nuevo producto en stock "%{name}"
notice: Se ha creado el nuevo producto en stock "%{name}"
derive:
title: Añade un artículo en stock desde plantilla
destroy:
@ -1493,6 +1759,7 @@ es:
show_stock_takings: Resumen del inventario
stock_count: 'Número de artículos'
stock_worth: 'Valor actual del stock:'
title: Existencias (%{article_count})
toggle_unavailable: Muestra/esconde los artículos no disponibles
view_options: Ver opciones
new:
@ -1500,6 +1767,7 @@ es:
title: Añade mi nuevo artículo de stock
show:
change_quantity: Cambia
datetime: Hora
new_quantity: Nueva cantidad
reason: Razón
stock_changes: Cambio de cantidades en stock
@ -1517,6 +1785,7 @@ es:
action_new: Crea un nuevo proveedor/a
articles: artículos (%{count})
confirm_del: Estas seguro de que quieres borrar al proveedor %{name}?
deliveries: entregas (%{count})
stock: en stock (%{count})
title: Proveedores
new:
@ -1582,9 +1851,10 @@ es:
accept_task: Aceptar tarea
confirm_delete_group: Estás seguro/a de que quieres borrar esta tarea y todas las tareas subsecuentes?
confirm_delete_single: Estás seguro/a de que quieres borrar esta tarea?
confirm_delete_single_from_group: Estás seguro/a de que quieres borrar esta tarea (y mantener las tareas recurrentes relacionadas)?
confirm_delete_single_from_group: Estás seguro/a de que quieres borrar esta tarea (y mantener las tareas recurrentes relacionadas)?
delete_group: Borrar esta tarea y las subsecuentes
edit_group: Edita recurrencia
hours: "%{count}h"
mark_done: Marca tarea como hecha
reject_task: Rechaza tarea
title: Muestra tarea
@ -1605,19 +1875,34 @@ es:
back: Volver
cancel: Cancelar
close: Cerrar
confirm_delete: '¿Realmente desea eliminar %{name}?'
confirm_restore: '¿Realmente desea restaurar %{name}?'
copy: Copia
delete: Eliminar
download: Descarga
edit: Editar
marks:
close: "&times;"
success: <i class="icon icon-ok"></i>
move: Mover
or_cancel: o cancelar
please_wait: Espera...
restore: Restaura
save: Guardar
search_placeholder: Busca ...
show: Mostrar
views:
pagination:
first: "&laquo;"
last: "&raquo;"
next: "&rsaquo;"
previous: "&lsaquo;"
truncate: "..."
workgroups:
edit:
title: Edita grupo de trabajo
error_last_admin_group: El último grupo con derechos de administrador no debe ser eliminado
error_last_admin_role: El rol de administrador del último grupo con derechos de administrador no puede ser retirado
index:
title: Grupos de trabajo
update:

View file

@ -14,7 +14,7 @@ fr:
gross_price: Prix TTC
manufacturer: Product-rice-eur
name: Nom
order_number: Numéro
order_number: Numéro
order_number_short: Numéro
origin: Lieu de production
price: Prix HT
@ -417,8 +417,8 @@ fr:
street: Rue
zip_code: Code postal
currency_unit: Monnaie
name: Nom
disable_members_overview: Désactiver la liste des membres
name: Nom
distribution_strategy: Stratégie de distribution
distribution_strategy_options:
first_order_first_serve: Distribuez d'abord à ceux qui ont commandé en premier
@ -864,7 +864,7 @@ fr:
error_invite_invalid: Ton invitation n'est pas ou plus valide.
error_token_invalid: Ton jeton de connexion n'est pas ou plus valide, essaie de cliquer à nouveau sur le lien.
reset_password:
notice: Tu vas maintenant recevoir un message contenant un lien qui te permettra de réinitialiser ton mot de passe.
notice: Tu vas maintenant recevoir un message contenant un lien qui te permettra de réinitialiser ton mot de passe.
update_password:
notice: Ton mot de passe a été mis à jour. Tu peux maintenant de connecter.
forgot_password:
@ -1097,7 +1097,7 @@ fr:
closed: décomptée
finished: clôturée
open: en cours
received: reçu
received: reçu
update:
notice: La commande a été mise à jour.
update_order_amounts:
@ -1349,7 +1349,7 @@ fr:
notice: La description du boulot a été mise à jour.
notice_converted: Le boulot a été converti en boulot ordinaire (sans répétition).
user:
more: Tu t'ennuies en ce moment? Il y aura sûrement du boulot pour toi %{tasks_link}.
more: Tu t'ennuies en ce moment? Il y aura sûrement du boulot pour toi %{tasks_link}.
tasks_link: par là-bas
title: Ton boulot
title_accepted: Boulots acceptés
@ -1374,7 +1374,7 @@ fr:
edit:
title: Modifier l'équipe
error_last_admin_group: Impossible de supprimer la dernière cellule avec privilèges administratrices.
error_last_admin_role: Les privilèges administratrices ne peuvent pas être retirés à la dernière cellule qui les possède.
error_last_admin_role: Les privilèges administratrices ne peuvent pas être retirés à la dernière cellule qui les possède.
index:
title: Équipes
update:

View file

@ -35,13 +35,19 @@ nl:
unit_quantity: Colligrootte
bank_account:
balance: Tegoed
bank_gateway: Bank gateway
description: Omschrijving
iban: IBAN
name: Naam
bank_gateway:
authorization: Autorisatiekoptekst
name: Naam
unattended_user: Gebruiker zonder toezicht
url: URL
bank_transaction:
amount: Bedrag
date: Datum
external_id: Extern ID
external_id: Externe ID
financial_link: Financiële link
iban: IBAN
reference: Referentie
@ -51,26 +57,27 @@ nl:
note: Notitie
supplier: Leverancier
document:
created_at: Upload op
created_by: Upload door
data: Data
created_at: Aangemaakt op
created_by: Aangemaakt door
data: Gegevens
mime: MIME-type
name: Naam
financial_transaction:
amount: Bedrag
created_on: Datum
financial_transaction_class: Financiële transactie klasse
financial_transaction_type: Financiële transactie type
financial_transaction_class: Financiële-transactieklasse
financial_transaction_type: Financiële-transactietype
note: Notitie
ordergroup: Huishouden
user: Ingevuld door
user: Ingevoerd door
financial_transaction_class:
ignore_for_account_balance: Negeren voor rekeningsaldo
name: Naam
financial_transaction_type:
bank_account: Bankrekening
name: Naam
financial_transaction_class: Klasse financiële transactie
name_short: Verkorte naam
name_short: Korte naam
group_order:
ordergroup: Huishouden
price: Totaal bestelling
@ -81,16 +88,16 @@ nl:
received: Ontvangen
result: Hoeveelheid
tolerance: Tolerantie
total_price: Som
total_price: Totaal
unit_price: Prijs/Eenheid
invoice:
amount: Bedrag
attachment: Bijlage
created_at: Gemaakt op
created_by: Gemaakt door
created_at: Aangemaakt op
created_by: Aangemaakt door
date: Factuurdatum
delete_attachment: Bijlage verwijderen
deliveries: Voorraad levering
deliveries: Voorraadlevering
deposit: Statiegeld in rekening gebracht
deposit_credit: Statiegeld teruggekregen
financial_link: Financiële link
@ -151,10 +158,10 @@ nl:
contact_address: Adres
contact_person: Contactpersoon
contact_phone: Telefoon
description: Omschrijving
description: Beschrijving
ignore_apple_restriction: Bestelstop vanwege appelpunten negeren
last_order: Laatste bestelling
last_user_activity: Laatst actief
last_user_activity: Laatste activiteit
name: Naam
user_tokens: Leden
stock_article:
@ -186,9 +193,14 @@ nl:
phone2: Telefoon 2
shared_sync_method: Hoe synchroniseren
url: Homepage
supplier_category:
name: Naam
description: Beschrijving
financial_transaction_class: Financiële-transactieklasse
bank_account: Bankrekening
task:
created_by: Gemaakt door
created_on: Gemaakt op
created_by: Aangemaakt door
created_on: Aangemaakt op
description: Beschrijving
done: Gedaan?
due_date: Voor wanneer?
@ -201,7 +213,7 @@ nl:
email: E-mail
first_name: Voornaam
iban: IBAN
last_activity: Laatst actief
last_activity: Laatste activiteit
last_login: Laatste aanmelding
last_name: Achternaam
name: Naam
@ -214,13 +226,13 @@ nl:
one: Werkgroep
other: Werkgroepen
workgroup:
description: Omschrijving
description: Beschrijving
name: Naam
role_admin: Beheer
role_article_meta: Artikelen
role_finance: Financiën
role_invoices: Facturen
role_orders: Bestellingen
role_orders: Beheer bestellingen
role_pickups: Ophaaldagen
role_suppliers: Leveranciers
user_tokens: Leden
@ -243,6 +255,8 @@ nl:
models:
article: Artikel
article_category: Categorie
bank_account: Bankrekening
bank_gateway: Betalingsdienst
bank_transaction: Banktransactie
delivery: Levering
financial_transaction: Financiële transactie
@ -254,10 +268,11 @@ nl:
order_comment: Commentaar
ordergroup:
one: Huishouden
other: Huishouden
other: Huishoudens
stock_article: Voorraadartikel
stock_taking: Inventaris
supplier: Leverancier
supplier_category: Leverancierscategorie
task: Taak
user: Gebruiker
workgroup: Werkgroep
@ -268,7 +283,7 @@ nl:
all_ordergroups: Alle huishoudens
all_users: Alle gebruikers
all_workgroups: Alle werkgroepen
created_at: gemaakt op
created_at: aangemaakt op
first_paragraph: Hier kun je de groepen en gebruikers van Foodsoft beheren.
groupname: Groepsnaam
members: leden
@ -276,16 +291,24 @@ nl:
new_ordergroup: Nieuw huishouden
new_user: Nieuwe gebruiker
new_workgroup: Nieuwe werkgroep
newest_groups: Nieuwste groepen
newest_users: Nieuwste gebruikers
title: Administratie
type: Type
username: Gebruikersnaam
newest_groups: nieuwste groepen
newest_users: nieuwste gebruikers
title: Beheer
type: type
username: gebruikersnaam
bank_accounts:
form:
title_edit: Bankrekening bewerken
title_new: Nieuwe bankrekening toevoegen
bank_gateways:
form:
title_edit: Betalingsdienst bewerken
title_new: Nieuwe betalingsdienst toevoegen
configs:
list:
key: Sleutel
title: Configuratielijst
value: Inhoud
value: Waarde
show:
submit: Opslaan
title: Configuratie
@ -297,7 +320,7 @@ nl:
schedule_title: Bestelrooster
tab_security:
default_roles_title: Toegang tot
default_roles_paragraph: "Ieder lid van de foodcoop heeft standaard toegang tot de volgende onderdelen:"
default_roles_paragraph: 'Ieder lid van de foodcoop heeft standaard toegang tot de volgende onderdelen:'
tab_tasks:
periodic_title: Periodieke taken
tabs:
@ -311,8 +334,11 @@ nl:
first_paragraph: Hier kunt u de klassen van financiële transacties en de bijbehorende typen financiële transacties beheren. Elke financiële transactie heeft een type, die je bij elke transactie moet selecteren, als je meer dan één type hebt gemaakt. De klassen financiële transacties kunnen worden gebruikt om de types financiële transacties te groeperen en zullen worden weergegeven als extra kolommen in het rekeningoverzicht, als er meer dan één is gecreëerd.
new_bank_account: Nieuwe bankrekening toevoegen
new_financial_transaction_class: Nieuwe klasse voor financiële transacties toevoegen
new_bank_gateway: Nieuwe betalingsdienst toevoegen
title: Financiën
transaction_types: Typen financiële transacties
supplier_categories: Leverancierscategorieën
new_supplier_category: Nieuwe leverancierscategorie
transaction_types:
name: Naam
new_financial_transaction_type: Nieuw type financiële transactie toevoegen
@ -411,6 +437,10 @@ nl:
workgroups:
members: leden
name: naam
supplier_categories:
form:
title_new: Leverancierscategorie toevoegen
title_edit: Leverancierscategorie bewerken
application:
controller:
error_authn: Aanmelden vereist!
@ -569,8 +599,8 @@ nl:
street: Adres, meestal is dit het aflever- en ophaaladres.
currency_space: Spatie toevoegen na valutasymbool.
currency_unit: Valutasymbool voor het tonen van prijzen.
custom_css: De layout van deze site kan gewijzigd worden door hier cascading stylesheets (CSS) in te voeren. Laat het leeg voor de standaardstijl.
email_from: Emails zullen lijken verzonden te zijn vanaf dit email adres. Laat het veld leeg om het contactadres van de foodcoop te gebruiken.
custom_css: Om de lay-out van deze site aan te passen, kunt u stijlwijzigingen invoeren met behulp van cascading stylesheets (CSS). Laat leeg voor de standaardstijl.
email_from: Het zal lijken alsof e-mails verzonden zijn vanaf dit e-mailadres. Laat het veld leeg om het contactadres van de foodcoop te gebruiken.
email_replyto: Vul dit in als je antwoord op mails van Foodsoft wilt ontvangen op een ander adres dan het bovenstaande.
email_sender: Emails worden verzonden vanaf dit emailadres. Om te voorkomen dat emails als spam worden tegengehouden, is het te adviseren het adres van de webserver op te nemen in het SPF record van het email domein.
help_url: Documentatie website.
@ -625,13 +655,13 @@ nl:
default_role_orders: Bestellingen
default_role_pickups: Ophaaldagen
default_role_suppliers: Leveranciers
disable_invite: Uitnodigingen deactiveren
disable_invite: Uitnodigingen uitschakelen
disable_members_overview: Ledenlijst deactiveren
email_from: From adres
email_replyto: Reply-to adres
email_sender: Sender adres
help_url: Documentatie URL
homepage: Homepage
email_from: Adres afzender
email_replyto: Antwoord-adres
email_sender: Adres afzender
help_url: URL documentatie
homepage: Hoofdpagina
ignore_browser_locale: Browsertaal negeren
minimum_balance: Minimum tegoed
name: Naam
@ -1310,11 +1340,11 @@ nl:
order_result_supplier:
subject: Nieuwe bestelling voor %{name}
text: |
Beste mijnheer/mevrouw,
Goeiedag,
Foodcoop %{foodcoop} wil graag een bestelling plaatsen.
%{foodcoop} wil graag een bestelling plaatsen.
Een PDF en spreadsheet vind u meegestuurd.
Een PDF en spreadsheet vindt u in bijlage.
Met vriendelijke groet,
%{user}

View file

@ -143,6 +143,13 @@ Rails.application.routes.draw do
end
end
post 'finance/group_order_invoice', to: 'group_order_invoices#create_multiple'
get 'orders/:order_id/group_order_invoices/download_all', to: 'group_order_invoices#download_all', as: 'download_all_group_order_invoices'
resources :group_order_invoices
resources :article_categories
########### Finance

View file

@ -1,5 +1,7 @@
project_id: 357447
api_token_env: CROWDIN_API_KEY
preserve_hierarchy: true
base_path: "."
files:
- source: /config/locales/en.yml
translation: /config/locales/%two_letters_code%.yml

View file

@ -0,0 +1,13 @@
class CreateGroupOrderInvoices < ActiveRecord::Migration[5.2]
def change
create_table :group_order_invoices do |t|
t.integer :group_order_id
t.bigint :invoice_number, unique: true, limit: 8
t.date :invoice_date
t.string :payment_method
t.timestamps
end
add_index :group_order_invoices, :group_order_id, unique: true
end
end

View file

@ -0,0 +1,5 @@
class AddCustomerNumberToGroup < ActiveRecord::Migration[7.0]
def change
add_column :groups, :customer_number, :string, unique: true
end
end

View file

@ -10,8 +10,8 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
create_table "action_text_rich_texts", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
ActiveRecord::Schema[7.0].define(version: 2023_08_22_120005) do
create_table "action_text_rich_texts", charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.text "body", size: :long
t.string "record_type", null: false
@ -21,7 +21,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true
end
create_table "active_storage_attachments", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "active_storage_attachments", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
@ -31,7 +31,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "active_storage_blobs", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
@ -43,19 +43,19 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "active_storage_variant_records", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "active_storage_variant_records", charset: "utf8mb4", force: :cascade do |t|
t.integer "blob_id", null: false
t.string "variation_digest", null: false
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
end
create_table "article_categories", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "article_categories", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", default: "", null: false
t.string "description"
t.index ["name"], name: "index_article_categories_on_name", unique: true
end
create_table "article_prices", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "article_prices", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "article_id", null: false
t.decimal "price", precision: 8, scale: 2, default: "0.0", null: false
t.decimal "tax", precision: 8, scale: 2, default: "0.0", null: false
@ -65,7 +65,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["article_id"], name: "index_article_prices_on_article_id"
end
create_table "articles", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "articles", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", default: "", null: false
t.integer "supplier_id", default: 0, null: false
t.integer "article_category_id", default: 0, null: false
@ -91,14 +91,14 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["type"], name: "index_articles_on_type"
end
create_table "assignments", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "assignments", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "user_id", default: 0, null: false
t.integer "task_id", default: 0, null: false
t.boolean "accepted", default: false
t.index ["user_id", "task_id"], name: "index_assignments_on_user_id_and_task_id", unique: true
end
create_table "bank_accounts", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "bank_accounts", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "iban"
t.string "description"
@ -108,14 +108,14 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.integer "bank_gateway_id"
end
create_table "bank_gateways", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "bank_gateways", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "url", null: false
t.string "authorization"
t.integer "unattended_user_id"
end
create_table "bank_transactions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "bank_transactions", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "bank_account_id", null: false
t.string "external_id"
t.date "date"
@ -129,7 +129,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["financial_link_id"], name: "index_bank_transactions_on_financial_link_id"
end
create_table "documents", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "documents", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name"
t.string "mime"
t.binary "data", size: :long
@ -140,16 +140,16 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["parent_id"], name: "index_documents_on_parent_id"
end
create_table "financial_links", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "financial_links", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.text "note"
end
create_table "financial_transaction_classes", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "financial_transaction_classes", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.boolean "ignore_for_account_balance", default: false, null: false
end
create_table "financial_transaction_types", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "financial_transaction_types", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.integer "financial_transaction_class_id", null: false
t.string "name_short"
@ -157,7 +157,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["name_short"], name: "index_financial_transaction_types_on_name_short"
end
create_table "financial_transactions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "financial_transactions", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "ordergroup_id"
t.decimal "amount", precision: 8, scale: 2, default: "0.0", null: false
t.text "note", null: false
@ -171,7 +171,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["reverts_id"], name: "index_financial_transactions_on_reverts_id", unique: true
end
create_table "group_order_article_quantities", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "group_order_article_quantities", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "group_order_article_id", default: 0, null: false
t.integer "quantity", default: 0
t.integer "tolerance", default: 0
@ -179,7 +179,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["group_order_article_id"], name: "index_group_order_article_quantities_on_group_order_article_id"
end
create_table "group_order_articles", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "group_order_articles", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "group_order_id", default: 0, null: false
t.integer "order_article_id", default: 0, null: false
t.integer "quantity", default: 0, null: false
@ -192,7 +192,17 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["order_article_id"], name: "index_group_order_articles_on_order_article_id"
end
create_table "group_orders", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "group_order_invoices", charset: "utf8mb4", force: :cascade do |t|
t.integer "group_order_id"
t.bigint "invoice_number"
t.date "invoice_date"
t.string "payment_method"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.index ["group_order_id"], name: "index_group_order_invoices_on_group_order_id", unique: true
end
create_table "group_orders", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "ordergroup_id"
t.integer "order_id", default: 0, null: false
t.decimal "price", precision: 8, scale: 2, default: "0.0", null: false
@ -205,7 +215,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["ordergroup_id"], name: "index_group_orders_on_ordergroup_id"
end
create_table "groups", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "groups", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "type", default: "", null: false
t.string "name", default: "", null: false
t.string "description"
@ -227,10 +237,11 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.date "break_end"
t.boolean "role_invoices", default: false, null: false
t.boolean "role_pickups", default: false, null: false
t.string "customer_number"
t.index ["name"], name: "index_groups_on_name", unique: true
end
create_table "invites", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "invites", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "token", default: "", null: false
t.datetime "expires_at", precision: nil, null: false
t.integer "group_id", default: 0, null: false
@ -239,7 +250,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["token"], name: "index_invites_on_token"
end
create_table "invoices", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "invoices", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "supplier_id"
t.string "number"
t.date "date"
@ -257,7 +268,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["supplier_id"], name: "index_invoices_on_supplier_id"
end
create_table "links", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "links", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "url", null: false
t.integer "workgroup_id"
@ -265,7 +276,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.string "authorization"
end
create_table "mail_delivery_status", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "mail_delivery_status", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.datetime "created_at", precision: nil
t.string "email", null: false
t.string "message", null: false
@ -274,13 +285,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["email"], name: "index_mail_delivery_status_on_email"
end
create_table "memberships", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "memberships", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "group_id", default: 0, null: false
t.integer "user_id", default: 0, null: false
t.index ["user_id", "group_id"], name: "index_memberships_on_user_id_and_group_id", unique: true
end
create_table "message_recipients", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "message_recipients", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "message_id", null: false
t.integer "user_id", null: false
t.integer "email_state", default: 0, null: false
@ -289,7 +300,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["user_id", "read_at"], name: "index_message_recipients_on_user_id_and_read_at"
end
create_table "messages", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "messages", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "sender_id"
t.string "subject", null: false
t.boolean "private", default: false
@ -300,7 +311,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.binary "received_email", size: :medium
end
create_table "oauth_access_grants", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "oauth_access_grants", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "resource_owner_id", null: false
t.integer "application_id", null: false
t.string "token", null: false
@ -312,7 +323,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
end
create_table "oauth_access_tokens", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "oauth_access_tokens", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "resource_owner_id"
t.integer "application_id"
t.string "token", null: false
@ -326,7 +337,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
end
create_table "oauth_applications", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "oauth_applications", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "uid", null: false
t.string "secret", null: false
@ -338,7 +349,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end
create_table "order_articles", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "order_articles", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "order_id", default: 0, null: false
t.integer "article_id", default: 0, null: false
t.integer "quantity", default: 0, null: false
@ -352,7 +363,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["order_id"], name: "index_order_articles_on_order_id"
end
create_table "order_comments", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "order_comments", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "order_id"
t.integer "user_id"
t.text "text"
@ -360,7 +371,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["order_id"], name: "index_order_comments_on_order_id"
end
create_table "orders", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "orders", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "supplier_id"
t.text "note"
t.datetime "starts", precision: nil
@ -379,7 +390,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["state"], name: "index_orders_on_state"
end
create_table "page_versions", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "page_versions", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "page_id"
t.integer "lock_version"
t.text "body"
@ -390,7 +401,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["page_id"], name: "index_page_versions_on_page_id"
end
create_table "pages", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "pages", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "title"
t.text "body"
t.string "permalink"
@ -404,20 +415,20 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["title"], name: "index_pages_on_title"
end
create_table "periodic_task_groups", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "periodic_task_groups", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.date "next_task_date"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
end
create_table "poll_choices", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "poll_choices", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "poll_vote_id", null: false
t.integer "choice", null: false
t.integer "value", null: false
t.index ["poll_vote_id", "choice"], name: "index_poll_choices_on_poll_vote_id_and_choice", unique: true
end
create_table "poll_votes", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "poll_votes", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "poll_id", null: false
t.integer "user_id", null: false
t.integer "ordergroup_id"
@ -427,7 +438,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["poll_id", "user_id", "ordergroup_id"], name: "index_poll_votes_on_poll_id_and_user_id_and_ordergroup_id", unique: true
end
create_table "polls", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "polls", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "created_by_user_id", null: false
t.string "name", null: false
t.text "description"
@ -447,7 +458,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["final_choice"], name: "index_polls_on_final_choice"
end
create_table "printer_job_updates", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "printer_job_updates", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "printer_job_id", null: false
t.datetime "created_at", precision: nil, null: false
t.string "state", null: false
@ -455,7 +466,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["printer_job_id", "created_at"], name: "index_printer_job_updates_on_printer_job_id_and_created_at"
end
create_table "printer_jobs", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "printer_jobs", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "order_id"
t.string "document", null: false
t.integer "created_by_user_id", null: false
@ -464,7 +475,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["finished_at"], name: "index_printer_jobs_on_finished_at"
end
create_table "settings", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "settings", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "var", null: false
t.text "value"
t.integer "thing_id"
@ -474,7 +485,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true
end
create_table "stock_changes", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "stock_changes", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "stock_event_id"
t.integer "order_id"
t.integer "stock_article_id"
@ -484,7 +495,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["stock_event_id"], name: "index_stock_changes_on_stock_event_id"
end
create_table "stock_events", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "stock_events", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.integer "supplier_id"
t.date "date"
t.datetime "created_at", precision: nil
@ -494,14 +505,14 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["supplier_id"], name: "index_stock_events_on_supplier_id"
end
create_table "supplier_categories", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "supplier_categories", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", null: false
t.string "description"
t.integer "financial_transaction_class_id"
t.integer "bank_account_id"
end
create_table "suppliers", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "suppliers", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", default: "", null: false
t.string "address", default: "", null: false
t.string "phone", default: "", null: false
@ -523,7 +534,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["name"], name: "index_suppliers_on_name", unique: true
end
create_table "tasks", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "tasks", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "name", default: "", null: false
t.text "description"
t.date "due_date"
@ -540,7 +551,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_085312) do
t.index ["workgroup_id"], name: "index_tasks_on_workgroup_id"
end
create_table "users", id: :integer, charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
create_table "users", id: :integer, charset: "utf8mb4", force: :cascade do |t|
t.string "nick"
t.string "password_hash", default: "", null: false
t.string "password_salt", default: "", null: false

View file

@ -10,6 +10,7 @@ de:
counts: '%{ordergroups} Bestellgruppen bestellten %{articles} verschiedene Produkte.'
no_selection: Wähle einen Artikel, um anzuzeigen wer ihn bestellt hat oder downloade eine Abholliste rechts.
article_info:
origin_in: in %{origin}
supplied_by: von %{supplier}
supplied_and_made_by: produziert von %{manufacturer}
supplied_by_made_by: von %{supplier} produziert von %{manufacturer}
@ -24,6 +25,8 @@ de:
piece: St.
unit: Einheit
add_new: Bestellgruppe hinzufügen
show:
title: ! '%{name}'
navigation:
receive: In Empfang nehmen
articles: Verteilen
@ -41,6 +44,7 @@ de:
title: Artikel für Bestellgruppe
payment_bar:
account_balance: Kontostand
new_pin: PIN
new_transaction: Neue Transaktion
payment: ! 'Zahlung:'
show:

View file

@ -1,5 +1,7 @@
es:
config:
hints:
use_current_orders: Activar el plugin de current_orders. Permite a los miembros con el permiso de la orden cambiar la cantidad de miembros en múltiples pedidos, usando tres nuevas pantallas en el menú de pedidos. Especialmente útil para los días de recogida.
keys:
use_current_orders: Pantallas extra de distribución
current_orders:
@ -23,6 +25,8 @@ es:
piece: pieza
unit: unidad
add_new: Añade un grupo de pedido...
show:
title: ! '%{name}'
navigation:
receive: Recibe
articles: Distribuye
@ -40,6 +44,7 @@ es:
title: Artículos por grupo de pedido
payment_bar:
account_balance: Balance de cuenta
new_pin: PIN
new_transaction: Nueva transacción
payment: ! 'Pago:'
show:

View file

@ -1,5 +1,6 @@
es:
discourse:
callback:
invalid_nonce: Nonce inválido
invalid_signature: Firma inválida
logged_in: Estás adentro!

View file

@ -6,6 +6,7 @@ de:
created_by: Erstellt von
data: Daten
mime: MIME-Typ
name: Name
config:
hints:
documents_allowed_extension: Eine Liste an erlaubten Dateiendungen getrennt durch Leerzeichen.

View file

@ -19,6 +19,7 @@ es:
documents:
create:
error: 'El documento no puede ser creado: %{error}'
not_allowed_mime: El tipo de archivo "%{mime}" no está permitido. Póngase en contacto con un administrador/a para incluirlo en la lista blanca.
notice: Se ha creado el documento
destroy:
error: 'El documento no puede ser borrado: %{error}'
@ -26,6 +27,14 @@ es:
notice: Se ha borrado el documento
form:
new: Nuevo Documento
new_folder: Carpeta nueva
submit: Crear
index:
new: Sube nuevo documento
new_folder: Crear una nueva carpeta
title: Documentos
move:
root_folder: Iniciar
title: Mover
update:
notice: Documento o carpeta fue movido

View file

@ -20,6 +20,7 @@ de:
workgroup_id: Arbeitsgruppe
messagegroup:
description: Beschreibung
name: Name
user_tokens: Mitglieder
models:
message: Nachricht
@ -84,6 +85,7 @@ de:
model:
reply_header: ! '%{user} schrieb am %{when}:'
reply_indent: ! '> %{line}'
reply_subject: ! 'Re: %{subject}'
new:
error_private: Nachricht ist privat!
hint_private: Nachricht erscheint nicht im Foodsoft Posteingang

View file

@ -59,6 +59,7 @@ es:
write_message: Escribir un mensaje
messagegroups:
index:
body: 'Un grupo de mensajes es como una lista de correo: puedes unirte (o salir) a cualquiera de ellos para recibir las actualizaciones enviadas a ese grupo.'
title: Grupos de mensaje
join:
error: 'No pudo unirse al grupo de mensaje: %{error}'
@ -72,27 +73,38 @@ es:
messages:
actionbar:
message_threads: Muestra como hilos
messagegroups: Suscribirse a este grupo
messages: Muestra como lista
new: Nuevo mensaje
create:
notice: El mensaje ha sido guardado y será enviado.
index:
title: Mensajes
messages:
reply: Responde
model:
reply_header: ! '%{user} escribió en %{when}:'
reply_indent: ! '> %{line}'
reply_subject: ! 'Re: %{subject}'
new:
error_private: Lo siento, este mensaje es privado.
hint_private: El mensaje no se muestra en el buzón de correo Foodsoft
list:
desc: ! 'Envía mensajes a todos los miembros a través de la lista de correo: %{list}'
mail: por ejemplo con un email a %{email}.
subscribe: Puedes leer más sobre la lista de correos en %{link}.
subscribe_msg: Quizás tengas que suscribirte a la lista primero.
wiki: Wiki (lista de correo de páginas)
message: mensaje
no_user_found: No se ha encontrado el usuario
order_item: "%{supplier_name} (Recoger: %{pickup})"
reply_to: Este mensaje es una respuesta a otro %{link}.
search: Busca ...
search_user: Busca usuario
title: Nuevo mensaje
show:
all_messages: Todos los mensajes
change_visibility: 'Cambiar'
from: ! 'De:'
group: 'Grupo:'
reply: Responde
@ -101,19 +113,35 @@ es:
subject: ! 'Asunto:'
title: Muestra mensaje
to: 'A:'
visibility: 'Visibilidad:'
visibility_private: 'Privado'
visibility_public: 'Público'
thread:
all_message_threads: Todos los hilos de mensaje
reply: Responde
toggle_private:
not_allowed: No puede cambiar la visibilidad del mensaje.
message_threads:
groupmessage_threads:
show_message_threads: muestra todos
index:
general: General
title: Hilos de mensaje
message_threads:
last_reply_at: Última respuesta el
last_reply_by: Última respuesta de
last_reply_by: Última respuesta de
started_at: Comenzado el
started_by: Comenzado por
show:
general: General
messages_mailer:
foodsoft_message:
footer: |
Respuesta: %{reply_url}
Ver mensaje en línea: %{msg_url}
Opciones de mensaje: %{profile_url}
footer_group: |
Enviado al grupo: %{group}
navigation:
admin:
messagegroups: Grupos de mensaje

View file

@ -17,6 +17,7 @@ de:
wiki:
all_pages: Alle Seiten
home: Startseite
title: Wiki
pages:
all:
new_page: Neue Seite anlegen
@ -67,6 +68,7 @@ de:
section_table: Tabellenformatierung
see_tables: siehe %{tables_link}
tables_link: Tabellen
text: Text
title: Schnelle Formatierungshilfe
unordered_list: Listen mit Punkten
wiki_link_ex: Foodsoft Wiki Seite
@ -94,9 +96,11 @@ de:
description: Variablen geben Informationen wieder, die an anderer Stelle definiert wurden. Wenn Du die Variable benutzt, wird sie mit ihrem Wert ersetzt, wenn sie angezeigt wird. Foodsoft hat eine Reihe von vordefinierten Variablen, wie zum Beispiel Name und Adresse deiner Foodcoop, Softwareversion und die Anzahl der Mitglieder und Lieferanten. In der Tabelle unten sind alle Variablen aufgeführt. Du kannst diese in Wiki-Seiten und der Fusszeile (in den Einstellungen) nutzen.
title: Foodsoft-Variablen
value: Aktueller Wert
variable: Variable
version:
author: ! 'Autor: %{user}'
date_format: ! '%a, %d.%m.%Y, %H:%M Uhr'
revert: Auf diese Version zurücksetzen
title: ! '%{title} - Version %{version}'
title_version: Version
view_current: Aktuelle Version sehen

View file

@ -16,24 +16,36 @@ es:
navigation:
wiki:
all_pages: Todas las páginas
home: Inicio
title: Wiki
pages:
all:
new_page: Crea nueva página
recent_changes: Cambios recientes
search:
action: Busca
placeholder: Título de página ..
site_map: Mapa web
title: Todas las páginas Wiki
title_list: Lista de páginas
body:
title_toc: Contenido
wikicloth_exception: 'Sentimos informar de que ha ocurrido un error al interpretar la página wiki: %{msg}. Por favor, intenta arreglarla y guarda la página de nuevo.'
create:
notice: La página ha sido creada
cshow:
error_noexist: La página no existe
redirect_notice: Redirigido desde %{page}...
destroy:
notice: La página '%{page}' y todas las subpáginas se han eliminado correctamente.
diff:
title: "%{title} - cambios de versión %{old} a %{new}"
edit:
title: Editar página
error_stale_object: Cuidado, la página ha sido editada por otra persona. Por favor, intenta de nuevo.
form:
help:
bold: negrita
external_link_ex: Enlace externo
external_links: Externo
heading: nivel %{level}
@ -41,18 +53,54 @@ es:
image_link_title: Título de la imagen
image_links: Imágenes
italic: itálicas
link_lists: Más en listas
link_table: Formato de tabla
link_templates: Plantillas
link_variables: Variables Foodsoft
list_item_1: Primer elemento de lista
list_item_2: Segundo elemento de lista
noformat: Sin Formato
ordered_list: Lista numerada
section_block: Estilo del párrafo
section_character: Estilo de las letras
section_link: Estilo de los enlaces
section_more: Más temas
section_table: Formato de tabla
see_tables: ver %{tables_link}
tables_link: Tablas
text: texto
title: Ayuda de formato rápido
unordered_list: Lista de artículos
wiki_link_ex: Página Wiki de Foodsoft
wiki_links: Enlaces Wiki
preview: Previsualizar
last_updated: Última actualización
new:
title: Crear una nueva página en la wiki
page_list_item:
date_format: ! '%a, %d %B %Y %H:%M:%S'
show:
date_format: ! '%d-%m-%y %H:%M'
delete: Eliminar página
delete_confirm: ! 'Advertencia: todas las subpáginas serán eliminadas también. ¿Estás seguro?'
diff: Comparar versiones
edit: Editar página
last_updated: Última actualización por <b>%{user}</b> el %{when}
subpages: subpáginas
title_versions: Versiones
versions: Versiones (%{count})
title: Título
update:
notice: La página fue actualizada
variables:
description: Las variables devuelven información de otro lugar. Cuando utilice la variable, se reemplazará por su valor cuando se muestre. Foodsoft tiene un número de variables predefinidas, como el nombre y la dirección de tu cooperativa, la versión del software, y el número de miembros y proveedores. Vea la siguiente tabla para todas las variables. Puede usarlas en páginas wiki así como en el pie de página (desde la pantalla de configuración).
title: Variables Foodsoft
value: Valor actual
variable: Variable
version:
author: ! 'Autor/a: %{user}'
date_format: ! '%a, %d-%m-%Y, %H:%M'
revert: Revertir a esta versión
title: ! '%{title} - versión %{version}'
title_version: Versión
view_current: Ver versión actual

View file

@ -0,0 +1,7 @@
require 'factory_bot'
FactoryBot.define do
factory :group_order_invoice do
group_order { create :group_order }
end
end

View file

@ -0,0 +1,72 @@
require_relative '../spec_helper'
feature GroupOrderInvoice, js: true do
let(:admin) { create :user, groups: [create(:workgroup, role_finance: true)] }
let(:user) { create :user, groups: [create(:ordergroup)] }
let(:article) { create :article, unit_quantity: 1 }
let(:order) { create :order, supplier: article.supplier, article_ids: [article.id], ends: Time.now } # need to ref article
let(:go) { create :group_order, order: order, ordergroup: user.ordergroup}
let(:oa) { order.order_articles.find_by_article_id(article.id) }
let(:ftt) { create :financial_transaction_type }
let(:goa) { create :group_order_article, group_order: go, order_article: oa }
include ActiveJob::TestHelper
before { login admin }
after { clear_enqueued_jobs }
it 'does not enqueue MailerJob when order is settled if tax_number or options not set' do
goa.update_quantities 2, 0
oa.update_results!
visit confirm_finance_order_path(id: order.id)
click_link_or_button I18n.t('finance.balancing.confirm.clear')
expect(NotifyGroupOrderInvoiceJob).not_to have_been_enqueued
end
it 'enqueues MailerJob when order is settled if tax_number or options are set' do
goa.update_quantities 2, 0
oa.update_results!
order.reload
FoodsoftConfig[:group_order_invoices] = { use_automatic_invoices: true }
FoodsoftConfig[:contact][:tax_number] = 12_345_678
visit confirm_finance_order_path(id: order.id, type: ftt)
expect(page).to have_selector(:link_or_button, I18n.t('finance.balancing.confirm.clear'))
click_link_or_button I18n.t('finance.balancing.confirm.clear')
expect(NotifyGroupOrderInvoiceJob).to have_been_enqueued
end
it 'generates Group Order Invoice when order is closed if tax_number is set' do
goa.update_quantities 2, 0
oa.update_results!
FoodsoftConfig[:contact][:tax_number] = 12_345_678
order.update!(state: 'closed')
go.reload
order.reload
visit finance_order_index_path
expect(page).to have_selector(:link_or_button, I18n.t('activerecord.attributes.group_order_invoice.links.generate'))
click_link_or_button I18n.t('activerecord.attributes.group_order_invoice.links.generate')
expect(GroupOrderInvoice.all.count).to eq(1)
end
it 'generates multiple Group Order Invoice for order when order is closed if tax_number is set' do
goa.update_quantities 2, 0
oa.update_results!
FoodsoftConfig[:contact][:tax_number] = 12_345_678
order.update!(state: 'closed')
order.reload
visit finance_order_index_path
expect(page).to have_selector(:link_or_button, I18n.t('activerecord.attributes.group_order_invoice.links.generate_with_date'))
click_link_or_button I18n.t('activerecord.attributes.group_order_invoice.links.generate_with_date')
expect(GroupOrderInvoice.all.count).to eq(1)
end
it 'does not generate Group Order Invoice when order is closed if tax_number not set' do
goa.update_quantities 2, 0
oa.update_results!
order.update!(state: 'closed')
order.reload
visit finance_order_index_path
expect(page).to have_content(I18n.t('activerecord.attributes.group_order_invoice.tax_number_not_set'))
end
end

View file

@ -0,0 +1,59 @@
require_relative '../spec_helper'
describe GroupOrderInvoice do
let(:user) { create :user, groups: [create(:ordergroup)] }
let(:supplier) { create :supplier }
let(:article) { create :article, supplier: supplier }
let(:order) { create :order }
let(:group_order) { create :group_order, order: order, ordergroup: user.ordergroup }
describe 'erroneous group order invoice' do
let(:goi) { create :group_order_invoice, group_order_id: group_order.id }
it 'does not create group order invoice if tax_number not set' do
expect { goi }.to raise_error(ActiveRecord::RecordInvalid, /.*/)
end
end
describe 'valid group order invoice' do
before do
FoodsoftConfig[:contact][:tax_number] = 123_457_8
end
invoice_number1 = Time.now.strftime("%Y%m%d") + '0001'
invoice_number2 = Time.now.strftime("%Y%m%d") + '0002'
let(:user2) { create :user, groups: [create(:ordergroup)] }
let(:goi1) { create :group_order_invoice, group_order_id: group_order.id }
let(:goi2) { create :group_order_invoice, group_order_id: group_order.id }
let(:group_order2) { create :group_order, order: order, ordergroup: user2.ordergroup }
let(:goi3) { create :group_order_invoice, group_order_id: group_order2.id }
let(:goi4) { create :group_order_invoice, group_order_id: group_order2.id, invoice_number: invoice_number1 }
it 'creates group order invoice if tax_number is set' do
expect(goi1).to be_valid
end
it 'sets invoice_number according to date' do
number = Time.now.strftime("%Y%m%d") + '0001'
expect(goi1.invoice_number).to eq(number.to_i)
end
it 'fails to create if group_order_id is used multiple times for creation' do
expect(goi1.group_order.id).to eq(group_order.id)
expect { goi2 }.to raise_error(ActiveRecord::RecordNotUnique)
end
it 'creates two different group order invoice with different invoice_numbers' do
expect(goi1.invoice_number).to eq(invoice_number1.to_i)
expect(goi3.invoice_number).to eq(invoice_number2.to_i)
end
it 'fails to create two different group order invoice with same invoice_numbers' do
goi1
expect { goi4 }.to raise_error(ActiveRecord::RecordInvalid)
end
end
end