accountant_clerk 0.6 → 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +7 -3
- data/Gemfile.lock +136 -85
- data/README.md +25 -23
- data/Rakefile +8 -0
- data/accountant_clerk.gemspec +2 -3
- data/app/assets/javascripts/accountant_report.js +4 -0
- data/app/assets/stylesheets/accountant_office.css +0 -2
- data/app/controllers/manage_controller_decorator.rb +20 -11
- data/app/views/manage/report.html.haml +26 -28
- data/config/i18n-tasks.yml +89 -0
- data/config/locales/en.yml +6 -7
- data/config/locales/fi.yml +6 -0
- data/lib/accountant_clerk/engine.rb +1 -1
- data/spec/controllers/orders_controller_spec.rb +1 -29
- data/spec/i18n_spec.rb +40 -0
- data/spec/routing/orders_routing_spec.rb +0 -4
- data/test_app/config/application.rb +1 -0
- data/test_app/config/environments/production.rb +1 -1
- data/test_app/config/environments/test.rb +1 -1
- data/test_app/db/migrate/20141114205525_clerks.office.rb +1 -1
- data/test_app/db/migrate/20141114205526_suppliers.office.rb +1 -1
- data/test_app/db/migrate/20141114205527_categories.office.rb +1 -1
- data/test_app/db/migrate/20141114205528_items.office.rb +1 -1
- data/test_app/db/migrate/20141114205529_orders.office.rb +1 -1
- data/test_app/db/migrate/20141114205530_baskets.office.rb +1 -1
- data/test_app/db/migrate/20141114205531_purchases.office.rb +1 -1
- data/test_app/db/migrate/20141114205532_products.office.rb +1 -1
- data/test_app/db/schema.rb +24 -24
- metadata +10 -6
- data/app/assets/stylesheets/flotomatic.css +0 -4
data/Rakefile
CHANGED
@@ -4,3 +4,11 @@
|
|
4
4
|
require File.expand_path('../test_app/config/application', __FILE__)
|
5
5
|
|
6
6
|
TestApp::Application.load_tasks
|
7
|
+
require 'bundler/gem_tasks'
|
8
|
+
|
9
|
+
desc 'Rebuild test and run specs'
|
10
|
+
task :full_test do
|
11
|
+
system("rake db:drop db:migrate RAILS_ENV=test && rspec")
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => 'full_test'
|
data/accountant_clerk.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.platform = Gem::Platform::RUBY
|
4
4
|
s.name = 'accountant_clerk'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.7'
|
6
6
|
s.summary = 'Simple reports for rubyclerks'
|
7
7
|
s.description = 'Simple reports that are not so simple anymore and let you analyse your shops performance'
|
8
8
|
s.required_ruby_version = '>= 1.9.3'
|
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.require_path = 'lib'
|
18
18
|
s.requirements << 'none'
|
19
19
|
|
20
|
-
s.add_runtime_dependency 'office_clerk', '~> 0.
|
20
|
+
s.add_runtime_dependency 'office_clerk', '~> 0.9'
|
21
21
|
s.add_runtime_dependency 'flot-rails', '~> 0.0.6'
|
22
22
|
end
|
23
|
-
|
@@ -4,13 +4,20 @@ ManageController.class_eval do
|
|
4
4
|
search = params[:q] || {}
|
5
5
|
search[:meta_sort] = "created_at asc"
|
6
6
|
if search[:created_at_gt].blank?
|
7
|
-
search[:created_at_gt] = (Time.now - 3.months)
|
7
|
+
search[:created_at_gt] = short_date(Time.now - 3.months)
|
8
8
|
else
|
9
|
-
search[:created_at_gt] =
|
9
|
+
search[:created_at_gt] =
|
10
|
+
begin
|
11
|
+
short_date(Time.zone.parse(search[:created_at_gt]).beginning_of_day)
|
12
|
+
rescue
|
13
|
+
I18n.l(Time.zone.now.beginning_of_month)
|
14
|
+
end
|
10
15
|
end
|
11
16
|
unless search[:created_at_lt].blank?
|
12
|
-
|
13
|
-
|
17
|
+
begin
|
18
|
+
search[:created_at_lt] = short_date(Time.zone.parse(search[:created_at_lt]).end_of_day)
|
19
|
+
rescue
|
20
|
+
end
|
14
21
|
end
|
15
22
|
@type = params[:type] || "Order"
|
16
23
|
search[:basket_kori_type_eq] = @type
|
@@ -33,14 +40,19 @@ ManageController.class_eval do
|
|
33
40
|
Item
|
34
41
|
end
|
35
42
|
@search = search_on.includes(:product).ransack(search)
|
36
|
-
gon.flot_options = { :series => { :bars => { :show => true , :barWidth => @days * 24*60*60*1000 } , :stack =>
|
43
|
+
gon.flot_options = { :series => { :bars => { :show => true , :barWidth => @days * 24*60*60*1000 } , :stack => true } ,
|
37
44
|
:legend => { :container => "#legend"} ,
|
38
45
|
:xaxis => { :mode => "time" }
|
39
46
|
}
|
40
47
|
group_data
|
41
|
-
# csv ? send_data( render_to_string( :csv , :layout => false) , :type => "application/csv" , :filename => "tilaukset.csv")
|
42
48
|
end
|
43
49
|
|
50
|
+
private
|
51
|
+
|
52
|
+
def short_date d
|
53
|
+
d = d.to_date unless d.is_a? Date
|
54
|
+
I18n.l( d , :format => :default)
|
55
|
+
end
|
44
56
|
def group_data
|
45
57
|
@group_by = (params[:group_by] || "all" )
|
46
58
|
all = @search.result(:distinct => true )
|
@@ -72,12 +84,9 @@ ManageController.class_eval do
|
|
72
84
|
when "by_supplier"
|
73
85
|
item.product.supplier.blank? ? "blank" : item.product.supplier.supplier_name
|
74
86
|
when "by_product"
|
75
|
-
item.product.name
|
76
|
-
when "by_product_line"
|
77
|
-
return "Basket #{item.basket.id}" if item.product.line_item? and not item.product.product
|
78
|
-
return "Basket #{item.basket.id}" unless item.product
|
79
87
|
item.product.full_name
|
80
|
-
|
88
|
+
when "by_product_line"
|
89
|
+
item.product.product ? item.product.product.name : item.product.name
|
81
90
|
else
|
82
91
|
pps = item.product.properties.detect{|p,v| p == @group_by}
|
83
92
|
pps ? pps.value : "blank"
|
@@ -1,7 +1,5 @@
|
|
1
1
|
- content_for :head do
|
2
|
-
= javascript_include_tag '
|
3
|
-
= javascript_include_tag 'jquery.flot.resize'
|
4
|
-
= javascript_include_tag 'jquery.flot.time'
|
2
|
+
= javascript_include_tag 'accountant_report.js'
|
5
3
|
.row
|
6
4
|
.col-md-9
|
7
5
|
#placeholder{:style => "width:800px;height:400px;"}
|
@@ -18,54 +16,54 @@
|
|
18
16
|
.col-md-4
|
19
17
|
= f.label :product_name_cont, t("name")
|
20
18
|
.col-md-8
|
21
|
-
= f.text_field :
|
19
|
+
= f.text_field :product_name_or_product_product_name_cont, :size => 15 , :class => "form-control"
|
20
|
+
.form-group
|
22
21
|
.col-md-4
|
23
22
|
= f.label :supplier , t(:supplier)
|
24
23
|
.col-md-8
|
25
|
-
= f.
|
26
|
-
.form-group
|
24
|
+
= f.collection_select :product_supplier_id_eq, Supplier.all, :id, :supplier_name, {:include_blank => true}, :class=>"form-control"
|
25
|
+
.form-group
|
27
26
|
.col-md-4
|
28
27
|
= f.label :category, t(:category)
|
29
28
|
.col-md-8
|
30
|
-
= f.
|
29
|
+
= f.collection_select :product_category_id_eq, Category.all, :id, :name, {:include_blank => true}, :class=>"form-control"
|
30
|
+
.form-group
|
31
31
|
.col-md-4
|
32
32
|
= f.label :property , t(:property)
|
33
33
|
.col-md-8
|
34
34
|
= f.text_field :product_properties_cont, :size => 15 , :class => "form-control"
|
35
|
-
.form-group
|
36
|
-
.col-md-
|
35
|
+
.form-group
|
36
|
+
.col-md-4
|
37
37
|
= f.label :price , t(:price)
|
38
|
-
.col-md-
|
39
|
-
= f.text_field :price_gt , :size => 6 , :class => "form-control"
|
40
|
-
.col-md-
|
41
|
-
|
42
|
-
.col-md-3
|
38
|
+
.col-md-4
|
39
|
+
= f.text_field :price_gt , :size => 6 , :class => "form-control"
|
40
|
+
.col-md-4
|
43
41
|
= f.text_field :price_lt , :size => 6 , :class => "form-control"
|
44
|
-
.form-group
|
42
|
+
.form-group
|
45
43
|
%label= t("date_range")
|
46
44
|
.date-range-filter
|
47
45
|
.col-md-6
|
48
46
|
= f.text_field :created_at_gt, :class => 'datepicker form-control' , :value => sort_date(:created_at_gt)
|
49
47
|
.col-md-6
|
50
48
|
= f.text_field :created_at_lt, :class => 'datepicker form-control', :value => sort_date(:created_at_lt)
|
51
|
-
.form-group
|
49
|
+
.form-group
|
52
50
|
%label= t("group_by")
|
53
51
|
%br/
|
54
52
|
= select_tag :group_by, options_for_select( group_options , @group_by) , :class => "form-control"
|
55
|
-
.form-group
|
56
|
-
.col-md-
|
53
|
+
.form-group
|
54
|
+
.col-md-4
|
57
55
|
= t(:price)
|
58
|
-
= radio_button_tag :price_or,
|
59
|
-
.col-md-
|
56
|
+
= radio_button_tag :price_or, :total , :total == @price_or
|
57
|
+
.col-md-4
|
58
|
+
= t(:profit)
|
59
|
+
= radio_button_tag :price_or, :profit , :profit == @price_or
|
60
|
+
.col-md-4
|
60
61
|
= t(:quantity)
|
61
|
-
= radio_button_tag :price_or,
|
62
|
-
.form-group
|
62
|
+
= radio_button_tag :price_or, :quantity , :quantity == @price_or
|
63
|
+
.form-group
|
63
64
|
.col-md-4
|
64
|
-
=
|
65
|
-
%span Day
|
65
|
+
= f.submit :month , :class => "btn btn-success" , :name => 'period'
|
66
66
|
.col-md-4
|
67
|
-
=
|
68
|
-
%span Week
|
67
|
+
= f.submit :week , :class => "btn btn-success" , :name => 'period'
|
69
68
|
.col-md-4
|
70
|
-
=
|
71
|
-
%span Month
|
69
|
+
= f.submit :day , :class => "btn btn-success" , :name => 'period'
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# i18n-tasks finds and manages missing and unused translations https://github.com/glebm/i18n-tasks
|
2
|
+
|
3
|
+
base_locale: en
|
4
|
+
## i18n-tasks detects locales automatically from the existing locale files
|
5
|
+
## uncomment to set locales explicitly
|
6
|
+
locales: [en, fi]
|
7
|
+
|
8
|
+
## i18n-tasks report locale, default: en, available: en, ru
|
9
|
+
# internal_locale: ru
|
10
|
+
|
11
|
+
# Read and write locale data
|
12
|
+
data:
|
13
|
+
## by default, translation data are read from the file system, or you can provide a custom data adapter
|
14
|
+
# adapter: I18n::Tasks::Data::FileSystem
|
15
|
+
|
16
|
+
# Locale files to read from
|
17
|
+
read:
|
18
|
+
- config/locales/%{locale}.yml
|
19
|
+
# - config/locales/*.%{locale}.yml
|
20
|
+
# - config/locales/**/*.%{locale}.yml
|
21
|
+
|
22
|
+
# key => file routes, matched top to bottom
|
23
|
+
write:
|
24
|
+
## E.g., write devise and simple form keys to their respective files
|
25
|
+
- ['{config}.*', 'config/locales/\1.%{locale}.yml']
|
26
|
+
# Catch-all
|
27
|
+
- config/locales/%{locale}.yml
|
28
|
+
# `i18n-tasks normalize -p` will force move the keys according to these rules
|
29
|
+
|
30
|
+
# YAML / JSON serializer options, passed to load / dump / parse / serialize
|
31
|
+
yaml:
|
32
|
+
write:
|
33
|
+
# do not wrap lines at 80 characters
|
34
|
+
line_width: -1
|
35
|
+
json:
|
36
|
+
write:
|
37
|
+
# pretty print JSON
|
38
|
+
indent: ' '
|
39
|
+
space: ' '
|
40
|
+
object_nl: "\n"
|
41
|
+
array_nl: "\n"
|
42
|
+
|
43
|
+
# Find translate calls
|
44
|
+
search:
|
45
|
+
## Default scanner finds t() and I18n.t() calls
|
46
|
+
# scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
|
47
|
+
|
48
|
+
## Paths to search in, passed to File.find
|
49
|
+
paths:
|
50
|
+
- app/
|
51
|
+
|
52
|
+
## Root for resolving relative keys (default)
|
53
|
+
# relative_roots:
|
54
|
+
# - app/views
|
55
|
+
|
56
|
+
## File.fnmatch patterns to exclude from search (default)
|
57
|
+
# exclude: ["*.jpg", "*.png", "*.gif", "*.svg", "*.ico", "*.eot", "*.ttf", "*.woff", "*.pdf"]
|
58
|
+
|
59
|
+
## Or, File.fnmatch patterns to include
|
60
|
+
# include: ["*.rb", "*.html.slim"]
|
61
|
+
|
62
|
+
## Google Translate
|
63
|
+
# # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
|
64
|
+
translation:
|
65
|
+
api_key: "AIzaSyCRjToD-btZK_eaaLeqKNmoh1fPoqhbAtQ"
|
66
|
+
|
67
|
+
## Consider these keys not missing
|
68
|
+
# ignore_missing:
|
69
|
+
# - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
|
70
|
+
# - '{devise,simple_form}.*'
|
71
|
+
|
72
|
+
## Consider these keys used
|
73
|
+
# ignore_unused:
|
74
|
+
# - 'activerecord.attributes.*'
|
75
|
+
# - '{devise,kaminari,will_paginate}.*'
|
76
|
+
# - 'simple_form.{yes,no}'
|
77
|
+
# - 'simple_form.{placeholders,hints,labels}.*'
|
78
|
+
# - 'simple_form.{error_notification,required}.:'
|
79
|
+
|
80
|
+
## Exclude these keys from `i18n-tasks eq-base' report
|
81
|
+
# ignore_eq_base:
|
82
|
+
# all:
|
83
|
+
# - common.ok
|
84
|
+
# fr,es:
|
85
|
+
# - common.brand
|
86
|
+
|
87
|
+
## Exclude these keys from all of the reports
|
88
|
+
#ignore:
|
89
|
+
# - kaminari.*
|
data/config/locales/en.yml
CHANGED
@@ -24,7 +24,7 @@ module AccountantClerk
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
initializer "accountant.precompile", :group => :all do |app|
|
27
|
-
app.config.assets.precompile += ["accountant_office.css" , "accountant_office.js"]
|
27
|
+
app.config.assets.precompile += ["accountant_office.css" , "accountant_office.js" , "accountant_report.js" ]
|
28
28
|
end
|
29
29
|
|
30
30
|
config.to_prepare &method(:activate).to_proc
|
@@ -5,7 +5,7 @@ describe OrdersController do
|
|
5
5
|
|
6
6
|
before :all do
|
7
7
|
create :admin unless Clerk.where(:admin => true).first
|
8
|
-
end
|
8
|
+
end
|
9
9
|
|
10
10
|
# This should return the minimal set of values that should be in the session
|
11
11
|
# in order to pass any filters (e.g. authentication) defined in
|
@@ -34,37 +34,9 @@ describe OrdersController do
|
|
34
34
|
it "assigns a new order as @order" do
|
35
35
|
get :new, {}, valid_session
|
36
36
|
expect(assigns(:order)).to be_kind_of(Order)
|
37
|
-
expect(assigns(:order)).to be_new_record
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "GET edit" do
|
42
|
-
it "assigns the requested order as @order" do
|
43
|
-
order = create :order
|
44
|
-
get :edit, {:id => order.to_param}, valid_session
|
45
|
-
expect(assigns(:order)).to eq(order)
|
46
37
|
end
|
47
38
|
end
|
48
39
|
|
49
|
-
describe "POST create" do
|
50
|
-
|
51
|
-
describe "with invalid params" do
|
52
|
-
it "assigns a newly created but unsaved order as @order" do
|
53
|
-
# Trigger the behavior that occurs when invalid params are submitted
|
54
|
-
allow_any_instance_of(Order).to receive(:save).and_return(false)
|
55
|
-
post :create, {:order => { :paid_on => ""}}, valid_session
|
56
|
-
expect(assigns(:order)).to be_kind_of(Order)
|
57
|
-
expect(assigns(:order)).to be_new_record
|
58
|
-
end
|
59
|
-
|
60
|
-
it "re-renders the 'new' template" do
|
61
|
-
# Trigger the behavior that occurs when invalid params are submitted
|
62
|
-
allow_any_instance_of(Order).to receive(:save).and_return(false)
|
63
|
-
post :create, {:order => { :paid_on => ""}}, valid_session
|
64
|
-
expect(response).to render_template(:edit)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
40
|
|
69
41
|
describe "PUT update" do
|
70
42
|
describe "with valid params" do
|
data/spec/i18n_spec.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'i18n/tasks'
|
3
|
+
require "i18n-spec"
|
4
|
+
|
5
|
+
describe 'locale:' do
|
6
|
+
|
7
|
+
Dir.glob('config/locales/*.yml') do |locale_file|
|
8
|
+
next if locale_file == "config/locales/config.yml"
|
9
|
+
next if locale_file.include? "extra"
|
10
|
+
context locale_file do
|
11
|
+
it { is_expected.to be_parseable }
|
12
|
+
it { is_expected.to have_valid_pluralization_keys }
|
13
|
+
it { is_expected.not_to have_missing_pluralization_keys }
|
14
|
+
it { is_expected.to have_one_top_level_namespace }
|
15
|
+
it { is_expected.not_to have_legacy_interpolations }
|
16
|
+
it { is_expected.to have_a_valid_locale }
|
17
|
+
it { is_expected.to be_a_complete_translation_of 'config/locales/en.yml' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context 'config/locales/en.yml' do
|
21
|
+
it { is_expected.to be_a_complete_translation_of 'config/locales/fi.yml' }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'I18n' do
|
26
|
+
let(:i18n) { I18n::Tasks::BaseTask.new }
|
27
|
+
let(:missing_keys) { i18n.missing_keys }
|
28
|
+
let(:unused_keys) { i18n.unused_keys }
|
29
|
+
|
30
|
+
it 'does not have missing keys' do
|
31
|
+
# needs work
|
32
|
+
# expect(missing_keys).to be_empty,
|
33
|
+
# "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'does not have unused keys' do
|
37
|
+
expect(i18n.unused_keys).to be_empty,
|
38
|
+
"#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
|
39
|
+
end
|
40
|
+
end
|
@@ -16,10 +16,6 @@ describe OrdersController do
|
|
16
16
|
expect(get("/orders/1")).to route_to("orders#show", :id => "1")
|
17
17
|
end
|
18
18
|
|
19
|
-
it "routes to #edit" do
|
20
|
-
expect(get("/orders/1/edit")).to route_to("orders#edit", :id => "1")
|
21
|
-
end
|
22
|
-
|
23
19
|
it "routes to #create" do
|
24
20
|
expect(post("/orders")).to route_to("orders#create")
|
25
21
|
end
|
@@ -24,5 +24,6 @@ module TestApp
|
|
24
24
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
25
25
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
26
26
|
# config.i18n.default_locale = :de
|
27
|
+
config.active_record.raise_in_transactional_callbacks = true
|
27
28
|
end
|
28
29
|
end
|
@@ -20,7 +20,7 @@ TestApp::Application.configure do
|
|
20
20
|
# config.action_dispatch.rack_cache = true
|
21
21
|
|
22
22
|
# Disable Rails's static asset server (Apache or nginx will already do this).
|
23
|
-
config.
|
23
|
+
config.serve_static_files = false
|
24
24
|
|
25
25
|
# Compress JavaScripts and CSS.
|
26
26
|
config.assets.js_compressor = :uglifier
|
@@ -13,7 +13,7 @@ TestApp::Application.configure do
|
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
15
|
# Configure static asset server for tests with Cache-Control for performance.
|
16
|
-
config.
|
16
|
+
config.serve_static_files = true
|
17
17
|
config.static_cache_control = "public, max-age=3600"
|
18
18
|
|
19
19
|
# Show full error reports and disable caching.
|