stockor-core 0.2
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +6 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +674 -0
- data/README.md +88 -0
- data/Rakefile +58 -0
- data/config/database.yml +9 -0
- data/db/migrate/20120110142845_create_skr_sequential_ids.rb +35 -0
- data/db/migrate/20140202185309_create_skr_gl_accounts.rb +15 -0
- data/db/migrate/20140202193316_create_skr_gl_periods.rb +16 -0
- data/db/migrate/20140202193318_create_skr_gl_transactions.rb +14 -0
- data/db/migrate/20140202193319_create_skr_gl_postings.rb +16 -0
- data/db/migrate/20140202193700_create_skr_gl_manual_entries.rb +13 -0
- data/db/migrate/20140213040608_create_skr_payment_terms.rb +16 -0
- data/db/migrate/20140220031700_create_skr_addresses.rb +19 -0
- data/db/migrate/20140220031800_create_skr_locations.rb +19 -0
- data/db/migrate/20140220190836_create_skr_vendors.rb +22 -0
- data/db/migrate/20140220203029_create_skr_customers.rb +22 -0
- data/db/migrate/20140224034759_create_skr_skus.rb +22 -0
- data/db/migrate/20140225032853_create_skr_sku_locs.rb +21 -0
- data/db/migrate/20140320030501_create_skr_uoms.rb +19 -0
- data/db/migrate/20140321031604_create_skr_sku_vendors.rb +18 -0
- data/db/migrate/20140322012143_create_skr_ia_reasons.rb +14 -0
- data/db/migrate/20140322014401_create_skr_inventory_adjustments.rb +16 -0
- data/db/migrate/20140322023453_create_skr_ia_lines.rb +18 -0
- data/db/migrate/20140322035024_create_skr_sku_trans.rb +21 -0
- data/db/migrate/20140322223912_create_skr_sales_orders.rb +27 -0
- data/db/migrate/20140322223920_create_skr_so_lines.rb +25 -0
- data/db/migrate/20140323001446_create_so_details_view.rb +81 -0
- data/db/migrate/20140327202102_create_skr_purchase_orders.rb +20 -0
- data/db/migrate/20140327202107_create_skr_po_lines.rb +25 -0
- data/db/migrate/20140327202207_create_skr_pick_tickets.rb +16 -0
- data/db/migrate/20140327202209_create_skr_pt_lines.rb +23 -0
- data/db/migrate/20140327224000_create_skr_invoices.rb +25 -0
- data/db/migrate/20140327224002_create_skr_inv_lines.rb +23 -0
- data/db/migrate/20140330232808_create_skr_sku_loc_details_view.rb +31 -0
- data/db/migrate/20140330232810_create_skr_sku_qty_details_view.rb +48 -0
- data/db/migrate/20140400164729_create_skr_vouchers.rb +22 -0
- data/db/migrate/20140400164733_create_skr_vo_lines.rb +21 -0
- data/db/migrate/20140401164729_create_skr_po_receipt.rb +16 -0
- data/db/migrate/20140401164740_create_skr_por_line.rb +21 -0
- data/db/migrate/20140422024010_create_skr_inv_details_view.rb +42 -0
- data/lib/generators/stockor/migrations/install_generator.rb +42 -0
- data/lib/skr/address.rb +97 -0
- data/lib/skr/business_entity.rb +25 -0
- data/lib/skr/concerns/acts_as_uom.rb +47 -0
- data/lib/skr/concerns/all.rb +30 -0
- data/lib/skr/concerns/association_extensions.rb +85 -0
- data/lib/skr/concerns/attr_accessor_with_default.rb +54 -0
- data/lib/skr/concerns/code_identifier.rb +43 -0
- data/lib/skr/concerns/export_associations.rb +52 -0
- data/lib/skr/concerns/export_join_tables.rb +39 -0
- data/lib/skr/concerns/export_methods.rb +104 -0
- data/lib/skr/concerns/export_scope.rb +66 -0
- data/lib/skr/concerns/exported_limit_evaluator.rb +17 -0
- data/lib/skr/concerns/gl_tran_extensions.rb +18 -0
- data/lib/skr/concerns/has_gl_transaction.rb +67 -0
- data/lib/skr/concerns/has_sku_loc_lines.rb +47 -0
- data/lib/skr/concerns/immutable_model.rb +32 -0
- data/lib/skr/concerns/inv_extensions.rb +24 -0
- data/lib/skr/concerns/is_order_like.rb +47 -0
- data/lib/skr/concerns/is_sku_loc_line.rb +65 -0
- data/lib/skr/concerns/json_attribute_access.rb +55 -0
- data/lib/skr/concerns/locked_fields.rb +84 -0
- data/lib/skr/concerns/pt_extensions.rb +22 -0
- data/lib/skr/concerns/pub_sub.rb +105 -0
- data/lib/skr/concerns/queries.rb +20 -0
- data/lib/skr/concerns/random_hash_code.rb +40 -0
- data/lib/skr/concerns/sanitize_json.rb +49 -0
- data/lib/skr/concerns/sku_extensions.rb +52 -0
- data/lib/skr/concerns/so_extensions.rb +30 -0
- data/lib/skr/concerns/state_machine.rb +62 -0
- data/lib/skr/concerns/track_modifications.rb +48 -0
- data/lib/skr/concerns/visible_id_identifier.rb +53 -0
- data/lib/skr/core.rb +30 -0
- data/lib/skr/core/configuration.rb +87 -0
- data/lib/skr/core/db.rb +82 -0
- data/lib/skr/core/db/migration_helpers.rb +178 -0
- data/lib/skr/core/db/migrations.rb +15 -0
- data/lib/skr/core/db/seed.rb +46 -0
- data/lib/skr/core/db/seed/chart_of_accounts.yml +168 -0
- data/lib/skr/core/db/seed/payment_terms.yml +60 -0
- data/lib/skr/core/logger.rb +36 -0
- data/lib/skr/core/numbers.rb +71 -0
- data/lib/skr/core/rails_engine.rb +5 -0
- data/lib/skr/core/standard_pricing_provider.rb +15 -0
- data/lib/skr/core/strings.rb +57 -0
- data/lib/skr/core/testing.rb +11 -0
- data/lib/skr/core/testing/assertions.rb +44 -0
- data/lib/skr/core/testing/fixtures.rb +25 -0
- data/lib/skr/core/testing/fixtures/skr/addresses.yml +53 -0
- data/lib/skr/core/testing/fixtures/skr/customers.yml +43 -0
- data/lib/skr/core/testing/fixtures/skr/gl_accounts.yml +86 -0
- data/lib/skr/core/testing/fixtures/skr/gl_manual_entries.yml +4 -0
- data/lib/skr/core/testing/fixtures/skr/gl_periods.yml +26 -0
- data/lib/skr/core/testing/fixtures/skr/gl_postings.yml +88 -0
- data/lib/skr/core/testing/fixtures/skr/gl_transactions.yml +35 -0
- data/lib/skr/core/testing/fixtures/skr/ia_lines.yml +7 -0
- data/lib/skr/core/testing/fixtures/skr/ia_reasons.yml +15 -0
- data/lib/skr/core/testing/fixtures/skr/inv_lines.yml +22 -0
- data/lib/skr/core/testing/fixtures/skr/inventory_adjustments.yml +6 -0
- data/lib/skr/core/testing/fixtures/skr/invoices.yml +10 -0
- data/lib/skr/core/testing/fixtures/skr/locations.yml +24 -0
- data/lib/skr/core/testing/fixtures/skr/payment_terms.yml +42 -0
- data/lib/skr/core/testing/fixtures/skr/pick_tickets.yml +4 -0
- data/lib/skr/core/testing/fixtures/skr/po_lines.yml +44 -0
- data/lib/skr/core/testing/fixtures/skr/po_receipts.yml +5 -0
- data/lib/skr/core/testing/fixtures/skr/por_lines.yml +13 -0
- data/lib/skr/core/testing/fixtures/skr/pt_lines.yml +12 -0
- data/lib/skr/core/testing/fixtures/skr/purchase_orders.yml +16 -0
- data/lib/skr/core/testing/fixtures/skr/sales_orders.yml +32 -0
- data/lib/skr/core/testing/fixtures/skr/sku_locs.yml +78 -0
- data/lib/skr/core/testing/fixtures/skr/sku_trans.yml +9 -0
- data/lib/skr/core/testing/fixtures/skr/sku_vendors.yml +35 -0
- data/lib/skr/core/testing/fixtures/skr/skus.yml +50 -0
- data/lib/skr/core/testing/fixtures/skr/so_lines.yml +71 -0
- data/lib/skr/core/testing/fixtures/skr/uoms.yml +61 -0
- data/lib/skr/core/testing/fixtures/skr/vendors.yml +48 -0
- data/lib/skr/core/testing/fixtures/skr/vo_lines.yml +12 -0
- data/lib/skr/core/testing/fixtures/skr/vouchers.yml +8 -0
- data/lib/skr/core/testing/helper.rb +18 -0
- data/lib/skr/core/testing/test_case.rb +17 -0
- data/lib/skr/core/version.rb +5 -0
- data/lib/skr/customer.rb +34 -0
- data/lib/skr/gl_account.rb +56 -0
- data/lib/skr/gl_manual_entry.rb +31 -0
- data/lib/skr/gl_period.rb +13 -0
- data/lib/skr/gl_posting.rb +54 -0
- data/lib/skr/gl_transaction.rb +174 -0
- data/lib/skr/ia_line.rb +129 -0
- data/lib/skr/ia_reason.rb +16 -0
- data/lib/skr/inv_line.rb +90 -0
- data/lib/skr/inventory_adjustment.rb +60 -0
- data/lib/skr/invoice.rb +159 -0
- data/lib/skr/location.rb +31 -0
- data/lib/skr/model.rb +37 -0
- data/lib/skr/null_user.rb +30 -0
- data/lib/skr/payment_term.rb +30 -0
- data/lib/skr/pick_ticket.rb +71 -0
- data/lib/skr/po_line.rb +69 -0
- data/lib/skr/po_receipt.rb +51 -0
- data/lib/skr/por_line.rb +80 -0
- data/lib/skr/pt_line.rb +74 -0
- data/lib/skr/purchase_order.rb +112 -0
- data/lib/skr/sales_order.rb +159 -0
- data/lib/skr/sequential_id.rb +23 -0
- data/lib/skr/sku.rb +99 -0
- data/lib/skr/sku_loc.rb +94 -0
- data/lib/skr/sku_tran.rb +111 -0
- data/lib/skr/sku_vendor.rb +26 -0
- data/lib/skr/so_line.rb +159 -0
- data/lib/skr/uom.rb +63 -0
- data/lib/skr/user_proxy.rb +60 -0
- data/lib/skr/validators/all.rb +2 -0
- data/lib/skr/validators/email.rb +17 -0
- data/lib/skr/validators/set.rb +18 -0
- data/lib/skr/vendor.rb +33 -0
- data/lib/skr/vo_line.rb +35 -0
- data/lib/skr/voucher.rb +119 -0
- data/lib/stockor/core.rb +9 -0
- data/stockor-core.gemspec +37 -0
- data/tasks/migrations.rake +23 -0
- data/tasks/publish.rake +8 -0
- data/test/address_test.rb +57 -0
- data/test/concerns/attr_with_default_test.rb +45 -0
- data/test/concerns/code_identifier_test.rb +46 -0
- data/test/concerns/export_associations_test.rb +7 -0
- data/test/concerns/export_methods_test.rb +31 -0
- data/test/concerns/export_scope_test.rb +16 -0
- data/test/concerns/exported_limits_test.rb +47 -0
- data/test/concerns/json_attribute_access_test.rb +27 -0
- data/test/concerns/pub_sub_test.rb +83 -0
- data/test/concerns/sanitize_json_test.rb +47 -0
- data/test/core/configuration_test.rb +24 -0
- data/test/core/numbers_test.rb +26 -0
- data/test/core/strings_test.rb +41 -0
- data/test/customer_test.rb +34 -0
- data/test/gl_account_test.rb +23 -0
- data/test/gl_manual_entry_test.rb +17 -0
- data/test/gl_period_test.rb +12 -0
- data/test/gl_posting_test.rb +39 -0
- data/test/gl_transaction_test.rb +58 -0
- data/test/ia_line_test.rb +68 -0
- data/test/ia_reason_test.rb +11 -0
- data/test/inv_line_test.rb +58 -0
- data/test/inventory_adjustment_test.rb +72 -0
- data/test/invoice_test.rb +63 -0
- data/test/location_test.rb +10 -0
- data/test/payment_term_test.rb +25 -0
- data/test/pick_ticket_test.rb +27 -0
- data/test/po_line_test.rb +36 -0
- data/test/po_receipt_test.rb +93 -0
- data/test/por_line_test.rb +79 -0
- data/test/pt_line_test.rb +29 -0
- data/test/purchase_order_test.rb +44 -0
- data/test/sales_order_test.rb +74 -0
- data/test/sku_loc_test.rb +50 -0
- data/test/sku_test.rb +45 -0
- data/test/sku_tran_test.rb +21 -0
- data/test/sku_vendor_test.rb +13 -0
- data/test/so_line_test.rb +89 -0
- data/test/test_helper.rb +1 -0
- data/test/uom_test.rb +14 -0
- data/test/vendor_test.rb +35 -0
- data/test/vo_line_test.rb +20 -0
- data/test/voucher_test.rb +35 -0
- data/yard_ext/all.rb +9 -0
- data/yard_ext/code_identifier_handler.rb +33 -0
- data/yard_ext/concern_meta_methods.rb +60 -0
- data/yard_ext/config_options.rb +27 -0
- data/yard_ext/exported_scope.rb +4 -0
- data/yard_ext/immutable_handler.rb +17 -0
- data/yard_ext/json_attr_accessor.rb +22 -0
- data/yard_ext/locked_fields_handler.rb +21 -0
- data/yard_ext/templates/default/layout/html/layout.erb +20 -0
- data/yard_ext/templates/default/method_details/html/github_link.erb +1 -0
- data/yard_ext/templates/default/method_details/setup.rb +3 -0
- data/yard_ext/validators.rb +1 -0
- data/yard_ext/visible_id_handler.rb +38 -0
- metadata +448 -0
data/lib/skr/uom.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
class Uom < Skr::Model
|
|
4
|
+
|
|
5
|
+
belongs_to :sku, :inverse_of=>:uoms
|
|
6
|
+
|
|
7
|
+
validates :price, :numericality=>true, :allow_nil=>false
|
|
8
|
+
validates :sku, :presence=>true, :on=>:update
|
|
9
|
+
validates :code, :presence=>true
|
|
10
|
+
validates :size, :numericality => true, :length=>{:minimum=>1}
|
|
11
|
+
validates :weight, :height, :width, :depth, :numericality=>{:greater_than=>0.1}, :allow_nil=>true
|
|
12
|
+
|
|
13
|
+
export_methods :combined_uom, mandatory: true
|
|
14
|
+
|
|
15
|
+
def combined_uom
|
|
16
|
+
if self.size.nil? || self.code.nil?
|
|
17
|
+
''
|
|
18
|
+
elsif 1 == self.size
|
|
19
|
+
self.code
|
|
20
|
+
else
|
|
21
|
+
"#{self.code}/#{self.size}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def has_dimensions?
|
|
26
|
+
! self.dimensions.include?(nil)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def dimensions
|
|
30
|
+
[ width, height, depth ]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def volume
|
|
34
|
+
if has_dimensions?
|
|
35
|
+
dimensions.inject(:*)
|
|
36
|
+
else
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def blank?
|
|
42
|
+
self.code.blank? || self.size.to_i == 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def self.ea
|
|
47
|
+
Uom.new({ :code=>'EA',:size=>1, :price=>0.0 })
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
end # Skr module
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
__END__
|
|
57
|
+
|
|
58
|
+
def for_public(user=nil,options={})
|
|
59
|
+
as_json({
|
|
60
|
+
:only=>%w{ code size base_price },
|
|
61
|
+
:methods=>%w{ combined_uom dimensions volume }
|
|
62
|
+
})
|
|
63
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# The UserProxy is a stand-in for the real user
|
|
4
|
+
# model that will be implementation specific by the user of Stockor Core
|
|
5
|
+
class UserProxy
|
|
6
|
+
|
|
7
|
+
# The user who's currently interacting with Stockor.
|
|
8
|
+
# Defaults to 0, indicating anonymous or unknown
|
|
9
|
+
# @return [Object,FixNum] whatever was set using scoped_to, or 0 if nothing was set
|
|
10
|
+
def self.current
|
|
11
|
+
Thread.current[:skr_user_proxy]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Retrieve the current id of the user we're proxying for.
|
|
15
|
+
# get's a bit complicated since we can proxy both for a user object
|
|
16
|
+
# or just the user's id
|
|
17
|
+
# @return [Fixnum] current user's ID. If the current user is not set, returns 0
|
|
18
|
+
def self.current_id
|
|
19
|
+
if self.current.nil?
|
|
20
|
+
0
|
|
21
|
+
else
|
|
22
|
+
self.current.is_a?(Fixnum) ? self.current : self.current.id
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# sets the user for the duration of the block
|
|
27
|
+
# @example Inside a Rails controller
|
|
28
|
+
#
|
|
29
|
+
# class DocumentsController < ApplicationController
|
|
30
|
+
# around_filter :set_skr_user
|
|
31
|
+
#
|
|
32
|
+
# # update's the Document's owner to current
|
|
33
|
+
# # But sets all the notes to be owned by admin
|
|
34
|
+
# def update_owner
|
|
35
|
+
# doc = Document.find(params[:id])
|
|
36
|
+
# doc.current_owner = Skr::UserProxy.current
|
|
37
|
+
# Skr::UserProxy.scoped_to( User.admin ) do
|
|
38
|
+
# doc.notes.each{ |note| note.set_owner_to_current! } # will set to Skr::UserProxy.current
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# private
|
|
43
|
+
#
|
|
44
|
+
# def set_skr_user
|
|
45
|
+
# user = SuperUserModel.find( session[:user] )
|
|
46
|
+
# Skr::UserProxy.scoped_to( user ) do
|
|
47
|
+
# yield
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# @return [UserProxy] self
|
|
53
|
+
def self.scoped_to( user )
|
|
54
|
+
prev_user, Thread.current[:skr_user_proxy] = self.current, user
|
|
55
|
+
yield user
|
|
56
|
+
ensure
|
|
57
|
+
Thread.current[:skr_user_proxy] = prev_user
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# A custom validator "email".
|
|
2
|
+
# Doesn't really validate an email completely
|
|
3
|
+
# It simply asserts that the email string has one (and only one)
|
|
4
|
+
# @ (at symbol). This is mainly
|
|
5
|
+
# to give user feedback and not to assert the e-mail validity.
|
|
6
|
+
|
|
7
|
+
class EmailValidator < ActiveModel::EachValidator
|
|
8
|
+
|
|
9
|
+
# Regex originated from the Devise gem
|
|
10
|
+
REGEX = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
|
|
11
|
+
|
|
12
|
+
def validate_each( rec, attr, value)
|
|
13
|
+
unless value.present? && value.match( REGEX )
|
|
14
|
+
rec.errors.add attr, options[:message] || 'does not appear to be a valid email'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# A custom validator "set". It's similar to :presence validator
|
|
2
|
+
# Unlike :presence, :set doesn't care whether the associated record is valid or not, just that it is present
|
|
3
|
+
# Also unlike :presence, it only works on belongs_to
|
|
4
|
+
class SetValidator < ActiveModel::EachValidator
|
|
5
|
+
|
|
6
|
+
def validate_each( record, attribute, value)
|
|
7
|
+
association = record.class.reflect_on_association( attribute )
|
|
8
|
+
|
|
9
|
+
if association.nil? || !association.belongs_to?
|
|
10
|
+
raise ArgumentError, "Cannot validate existence on #{record.class} #{attribute}, not a :belongs_to association"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
if record.send( attribute ).nil?
|
|
14
|
+
record.errors.add( attribute, "is not set")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/skr/vendor.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# Vendors is a companies you purchase goods and services from.
|
|
4
|
+
# They have both a billing and shipping address,
|
|
5
|
+
# a gl account that payables should be applied against, and a payment term.
|
|
6
|
+
class Vendor < Skr::Model
|
|
7
|
+
|
|
8
|
+
# Common code shared with {Customer}
|
|
9
|
+
include BusinessEntity
|
|
10
|
+
|
|
11
|
+
belongs_to :gl_payables_account, class_name: 'Skr::GlAccount', export: true
|
|
12
|
+
belongs_to :gl_freight_account, class_name: 'Skr::GlAccount', export: true
|
|
13
|
+
|
|
14
|
+
has_many :purchase_orders, inverse_of: :vendor
|
|
15
|
+
has_many :vouchers, inverse_of: :vendor
|
|
16
|
+
has_many :vendor_skus, class_name: 'Skr::SkuVendor', inverse_of: :vendor
|
|
17
|
+
|
|
18
|
+
delegate_and_export :gl_payables_account_number
|
|
19
|
+
validates :gl_payables_account, set: true
|
|
20
|
+
|
|
21
|
+
has_many :sku_vendors
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def set_defaults
|
|
26
|
+
self.terms ||= PaymentTerm.find_by_code(Core.config.customer_terms_code)
|
|
27
|
+
self.gl_payables_account ||= GlAccount.default_for( :ap )
|
|
28
|
+
self.gl_freight_account ||= GlAccount.default_for( :freight )
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end # Skr module
|
data/lib/skr/vo_line.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
class VoLine < Skr::Model
|
|
4
|
+
|
|
5
|
+
acts_as_uom
|
|
6
|
+
|
|
7
|
+
is_sku_loc_line parent: 'voucher'
|
|
8
|
+
|
|
9
|
+
belongs_to :voucher
|
|
10
|
+
belongs_to :sku_vendor
|
|
11
|
+
belongs_to :po_line
|
|
12
|
+
has_one :sku, :through => :sku_vendor, export: true
|
|
13
|
+
|
|
14
|
+
validates :sku_vendor, :voucher, set: true
|
|
15
|
+
validates :sku_code, :description, :presence => true
|
|
16
|
+
|
|
17
|
+
validate :qty, numericality: { gt: 0 }
|
|
18
|
+
|
|
19
|
+
before_validation :set_defaults, one: :create
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def set_defaults
|
|
24
|
+
if po_line
|
|
25
|
+
self.sku_vendor = po_line.sku.sku_vendors.for_vendor( self.voucher.vendor )
|
|
26
|
+
%w{ price sku_code part_code description uom_code uom_size }.each do | attr |
|
|
27
|
+
self[ attr ] ||= po_line[ attr ]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
end # Skr module
|
data/lib/skr/voucher.rb
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# A voucher is a record of a {Vendor}'s demand for payment, or a record of
|
|
4
|
+
# It transistions through the following states
|
|
5
|
+
#
|
|
6
|
+
# * Saved; A {PurchaseOrder} has been recieved but an Invoice has not been received fromt the Vendor
|
|
7
|
+
# * It credit's each line's {Sku#gl_asset_account} and debit's the System default inventory_receipts_clearing
|
|
8
|
+
# * Confirmed; An Invoice has been received and verified as accurate.
|
|
9
|
+
# * Debit: {Vendor#gl_payables_account}, Credit: inventory_receipts_clearing
|
|
10
|
+
# * Paid; A payment has been made against the Voucher
|
|
11
|
+
# * Debit {Vendor#gl_payables_account}, Credit: Deposit clearing account
|
|
12
|
+
class Voucher < Skr::Model
|
|
13
|
+
|
|
14
|
+
has_visible_id
|
|
15
|
+
|
|
16
|
+
has_sku_loc_lines
|
|
17
|
+
|
|
18
|
+
belongs_to :vendor, export: true
|
|
19
|
+
belongs_to :customer, export: true
|
|
20
|
+
|
|
21
|
+
belongs_to :purchase_order
|
|
22
|
+
belongs_to :terms, :class_name=>'Skr::PaymentTerm', export: true
|
|
23
|
+
belongs_to :location
|
|
24
|
+
|
|
25
|
+
has_many :gl_transactions, :as=>:source
|
|
26
|
+
has_many :lines, :class_name=>'Skr::VoLine', export: { writable: true },
|
|
27
|
+
:inverse_of=>:voucher, :autosave=>true, validate: true
|
|
28
|
+
|
|
29
|
+
before_validation :set_defaults, :on=>:create
|
|
30
|
+
|
|
31
|
+
export_scope :with_details, lambda { | *args |
|
|
32
|
+
compose_query_using_detail_view( view: 'vo_details', join_to: 'voucher_id' )
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export_scope :unpaid, lambda{ | unused=nil |
|
|
36
|
+
where(['vouchers.state <> ? and payment_lines.id is null', 'pending']).includes(:payment_line)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
state_machine do
|
|
40
|
+
state :pending, initial: true
|
|
41
|
+
state :confirmed
|
|
42
|
+
state :paid
|
|
43
|
+
|
|
44
|
+
event :mark_confirmed do
|
|
45
|
+
transitions from: :pending, to: :confirmed
|
|
46
|
+
before :record_confirmation_in_gl
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
event :mark_paid do
|
|
50
|
+
transitions from: :confirmed, to: :paid, guards: :ensure_payment_line
|
|
51
|
+
before :record_payment_in_gl
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def po_receipt=(por)
|
|
58
|
+
self.vendor = por.vendor
|
|
59
|
+
self.purchase_order = por.purchase_order
|
|
60
|
+
self.terms = self.purchase_order.terms
|
|
61
|
+
self.refno = por.refno
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# def payment_line=(pl)
|
|
65
|
+
# pl.refno = self.refno
|
|
66
|
+
# pl.description = "Payment on PO #{self.visible_id}"
|
|
67
|
+
# super
|
|
68
|
+
# end
|
|
69
|
+
|
|
70
|
+
# def description_for_gl_transaction(gl_tran)
|
|
71
|
+
# end
|
|
72
|
+
|
|
73
|
+
# def does_create_own_gl_records?
|
|
74
|
+
# true
|
|
75
|
+
# end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def ensure_payment_line
|
|
80
|
+
payment_line.present?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def set_defaults
|
|
84
|
+
# self.freight ||= 0.0
|
|
85
|
+
if self.purchase_order
|
|
86
|
+
self.vendor = self.purchase_order.vendor
|
|
87
|
+
#self.location = self.purchase_order.location
|
|
88
|
+
self.terms ||= self.purchase_order.terms
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def record_confirmation_in_gl
|
|
95
|
+
self.confirmation_date ||= Date.today
|
|
96
|
+
GlTransaction.push_or_save(
|
|
97
|
+
:owner => self, amount: total,
|
|
98
|
+
:debit => vendor.gl_payables_account,
|
|
99
|
+
:credit => GlAccount.default_for( :inventory_receipts_clearing ),
|
|
100
|
+
:options => { description: "Voucher #{self.visible_id}" }
|
|
101
|
+
)
|
|
102
|
+
true
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def record_payment_in_gl
|
|
106
|
+
gl = self.gl_transactions.build({
|
|
107
|
+
:source =>self,
|
|
108
|
+
:location => self.purchase_order.location,
|
|
109
|
+
:amount =>self.total,
|
|
110
|
+
:description =>'Voucher Payment' })
|
|
111
|
+
gl.credit.account = self.vendor.gl_payables_account
|
|
112
|
+
gl.debit.account = self.payment_line.payment.bank_account.gl_account
|
|
113
|
+
gl.save!
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
end # Skr module
|
data/lib/stockor/core.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'skr/core/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
|
|
8
|
+
spec.name = "stockor-core"
|
|
9
|
+
spec.version = Skr::Core::VERSION
|
|
10
|
+
spec.authors = ["Nathan Stitt"]
|
|
11
|
+
spec.email = ["nathan@argosity.com"]
|
|
12
|
+
|
|
13
|
+
spec.summary = %q{Stockor Core contains the models for the Stockor ERP system}
|
|
14
|
+
spec.description = %q{Stockor Core contains the ActiveRecord models and business logic for the Stockor ERP system}
|
|
15
|
+
|
|
16
|
+
spec.homepage = "http://stockor.org/"
|
|
17
|
+
spec.license = "GPL-3.0"
|
|
18
|
+
|
|
19
|
+
spec.files = `git ls-files`.split($/)
|
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
|
22
|
+
spec.require_paths = ["lib"]
|
|
23
|
+
|
|
24
|
+
spec.required_ruby_version = '>= 2.0'
|
|
25
|
+
spec.add_dependency 'activerecord', '~> 4.1'
|
|
26
|
+
spec.add_dependency 'pg', '~> 0.17'
|
|
27
|
+
spec.add_dependency 'aasm', '~>3.1'
|
|
28
|
+
spec.add_dependency "require_all", '~> 1.3'
|
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
|
30
|
+
spec.add_development_dependency "rake"
|
|
31
|
+
spec.add_development_dependency "guard"
|
|
32
|
+
spec.add_development_dependency "growl"
|
|
33
|
+
spec.add_development_dependency "pry-plus"
|
|
34
|
+
spec.add_development_dependency "guard-minitest"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
require 'active_support/core_ext/string/strip'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'skr/core'
|
|
5
|
+
## quite a bit of this is cribbed from Sinatra ActiveRecord
|
|
6
|
+
|
|
7
|
+
load 'active_record/railties/databases.rake'
|
|
8
|
+
require 'rake'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
namespace :db do
|
|
12
|
+
|
|
13
|
+
task :environment do
|
|
14
|
+
Skr::Core::DB.configure_rake_environment
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "create an ActiveRecord migration"
|
|
18
|
+
task :create_migration,[ :name ] do | t, args |
|
|
19
|
+
Skr::Core::DB.create_migration( "create_skr_" + args[:name] )
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
end
|
data/tasks/publish.rake
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require_relative 'test_helper'
|
|
2
|
+
|
|
3
|
+
class AddressTest < Skr::TestCase
|
|
4
|
+
|
|
5
|
+
def test_creation
|
|
6
|
+
addr=Address.new( name:" a test", email:"test@test.com" )
|
|
7
|
+
assert_saves addr
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_email_with_name
|
|
11
|
+
addr=Address.new( email: 'john@mcauthor.com', name: 'John D. McAuthor' )
|
|
12
|
+
assert_equal "John D. McAuthor <john@mcauthor.com>", addr.email_with_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_blankness
|
|
16
|
+
addr = Address.blank
|
|
17
|
+
assert addr.blank?, "Blank address isn't blank?"
|
|
18
|
+
%w{ name line1 city state postal_code }.each do | attr |
|
|
19
|
+
assert addr.blank?
|
|
20
|
+
addr[ attr ] = "something"
|
|
21
|
+
end
|
|
22
|
+
refute addr.blank?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_separated_name
|
|
26
|
+
addr=Address.new( name: 'John D McAuthor' )
|
|
27
|
+
assert_equal 'John', addr.seperated_name[:first]
|
|
28
|
+
assert_equal 'McAuthor', addr.seperated_name[:last]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_selective_validations
|
|
32
|
+
addr=Address.blank
|
|
33
|
+
assert addr.save
|
|
34
|
+
addr.enable_validations
|
|
35
|
+
refute addr.save
|
|
36
|
+
%w{ name line1 city state postal_code }.each do | attr |
|
|
37
|
+
addr[ attr ] = "something"
|
|
38
|
+
end
|
|
39
|
+
assert addr.save
|
|
40
|
+
addr.enable_validations include_email: true
|
|
41
|
+
refute addr.save
|
|
42
|
+
addr.email = "test" # <- no '@'
|
|
43
|
+
refute addr.save
|
|
44
|
+
addr.email = "test@test.com" # <- no '@'
|
|
45
|
+
assert addr.save
|
|
46
|
+
addr.enable_validations include_phone: true
|
|
47
|
+
refute addr.save
|
|
48
|
+
addr.phone = "555-555-5555"
|
|
49
|
+
assert addr.save
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_converting_to_string
|
|
53
|
+
addr = skr_addresses(:office)
|
|
54
|
+
assert_equal "Argosity Office\n619 E Capitol Ave\nJefferson City Missouri, 65101", addr.to_s
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|