accountant_clerk 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|