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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
class InventoryAdjustment < Skr::Model
|
|
4
|
+
|
|
5
|
+
has_visible_id
|
|
6
|
+
has_gl_transaction if: :should_apply_gl?
|
|
7
|
+
|
|
8
|
+
has_one :gl_transaction, :as=>:source, :inverse_of=>:source
|
|
9
|
+
|
|
10
|
+
belongs_to :location, export: true
|
|
11
|
+
belongs_to :reason, :class_name=>'Skr::IaReason', export: true
|
|
12
|
+
|
|
13
|
+
has_many :lines, :class_name=>'Skr::IaLine', :inverse_of=>:inventory_adjustment, export: { writable:true }
|
|
14
|
+
|
|
15
|
+
validates :reason, :location, :set=>true
|
|
16
|
+
validate :ensure_state_is_savable
|
|
17
|
+
validates_associated :lines
|
|
18
|
+
|
|
19
|
+
delegate_and_export :location_code
|
|
20
|
+
delegate_and_export :reason_code
|
|
21
|
+
|
|
22
|
+
state_machine do
|
|
23
|
+
state :pending , :initial=>true
|
|
24
|
+
state :applied
|
|
25
|
+
event :mark_applied do
|
|
26
|
+
transitions from: :pending, to: :applied
|
|
27
|
+
before :apply_adjustment
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def should_apply_gl?
|
|
34
|
+
state_event == :mark_applied
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def attributes_for_gl_transaction
|
|
38
|
+
{ source: self, location: location,
|
|
39
|
+
description: "IA #{self.visible_id}" }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def ensure_state_is_savable
|
|
43
|
+
if applied? && state_was == 'applied'
|
|
44
|
+
errors.add('base' , "Cannot update record once it's approved and applied")
|
|
45
|
+
return false
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def apply_adjustment
|
|
50
|
+
self.lines.each do | line |
|
|
51
|
+
next if line.is_applied?
|
|
52
|
+
line.unlock_adjusting{ line.adjust_qty! }
|
|
53
|
+
end
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
end # Skr module
|
data/lib/skr/invoice.rb
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# Invoices constitute a demand for payment for goods that have been delivered to a {Customer}.
|
|
4
|
+
# A invoice contains:
|
|
5
|
+
#
|
|
6
|
+
# * Customer contact information
|
|
7
|
+
# * An inventory location that goods will be taken from.
|
|
8
|
+
# * The customer provided {PurchaseOrder} Number
|
|
9
|
+
# * The Payment Terms that were extended. This will control how much time the Customer has to pay the invoice in full.
|
|
10
|
+
# * One or more SKUs, the quantity desired for each and the selling price for them.
|
|
11
|
+
#
|
|
12
|
+
# While an {Invoice} often originates with a {SalesOrder}, it does not have to.
|
|
13
|
+
# Sales that take place in a retail environment where the customer selects
|
|
14
|
+
# the goods and pays for them immediately do not require a sales order record.
|
|
15
|
+
#
|
|
16
|
+
# Once an invoice is saved, it immediately removes the SKUs from the {SkuLoc}
|
|
17
|
+
# and generates corresponding General Ledger entries debiting the asset account
|
|
18
|
+
# and crediting the customers receivables account.
|
|
19
|
+
#
|
|
20
|
+
# When payment is received against the Invoice,
|
|
21
|
+
# the receivables account is debited and the payments holding account is credited.
|
|
22
|
+
#
|
|
23
|
+
# invoice = Invoice.new( customer: Customer.find_by_code("ACME")
|
|
24
|
+
# invoice.lines.build({ sku: Sku.find_by_code('LABOR'), qty: 1, price: 8.27 })
|
|
25
|
+
# invoice.save
|
|
26
|
+
|
|
27
|
+
class Invoice < Skr::Model
|
|
28
|
+
|
|
29
|
+
has_visible_id
|
|
30
|
+
has_random_hash_code
|
|
31
|
+
has_gl_transaction
|
|
32
|
+
is_order_like
|
|
33
|
+
has_additional_events :amount_paid_change
|
|
34
|
+
|
|
35
|
+
belongs_to :sales_order, export: true
|
|
36
|
+
belongs_to :customer, export: true
|
|
37
|
+
belongs_to :location, export: true
|
|
38
|
+
belongs_to :terms, class_name: 'Skr::PaymentTerm', export: true
|
|
39
|
+
belongs_to :pick_ticket, inverse_of: :invoice, export: true
|
|
40
|
+
belongs_to :billing_address, class_name: 'Skr::Address', export: { writable: true }
|
|
41
|
+
belongs_to :shipping_address, class_name: 'Skr::Address', export: { writable: true }
|
|
42
|
+
|
|
43
|
+
has_many :gl_transactions, :as=>:source
|
|
44
|
+
|
|
45
|
+
has_many :lines, -> { order(:position) }, class_name: 'Skr::InvLine', inverse_of: :invoice,
|
|
46
|
+
extend: Concerns::INV::Lines, export: { writable: true }
|
|
47
|
+
|
|
48
|
+
before_save :maybe_mark_paid
|
|
49
|
+
|
|
50
|
+
before_validation :set_defaults, on: :create
|
|
51
|
+
|
|
52
|
+
validates :customer, :location, set: true
|
|
53
|
+
validate :ensure_location_matches_so
|
|
54
|
+
|
|
55
|
+
scope :open_for_customer, lambda{ | customer |
|
|
56
|
+
where([ "customer_id=? and state != 'paid'", customer.is_a?(Customer) ? customer.id : customer ])
|
|
57
|
+
}, export: true
|
|
58
|
+
|
|
59
|
+
scope :with_details, lambda { |should_use=true |
|
|
60
|
+
compose_query_using_detail_view( view: 'inv_details', join_to: 'invoice_id' )
|
|
61
|
+
}, export: true
|
|
62
|
+
|
|
63
|
+
state_machine do
|
|
64
|
+
state :open, initial: true
|
|
65
|
+
state :paid
|
|
66
|
+
state :partial
|
|
67
|
+
event :mark_paid do
|
|
68
|
+
transitions from: [:open,:partial], to: :paid
|
|
69
|
+
before :apply_balances
|
|
70
|
+
end
|
|
71
|
+
event :mark_partial do
|
|
72
|
+
transitions from: [:open,:partial], to: :partial
|
|
73
|
+
before :apply_balances
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def initialize(attributes = {})
|
|
78
|
+
super
|
|
79
|
+
self.invoice_date = Date.today
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @return [BigDecimal] total - amount_paid
|
|
83
|
+
def unpaid_amount
|
|
84
|
+
self.total - amount_paid
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @return [Boolean] is the invoice paid in full
|
|
88
|
+
def fully_paid?
|
|
89
|
+
unpaid_amount <= 0
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
# attributes for GlTransaction
|
|
95
|
+
def attributes_for_gl_transaction
|
|
96
|
+
{ location: location, source: self,
|
|
97
|
+
description: "INV #{self.visible_id}" }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# set the state if the amount_paid was changed
|
|
101
|
+
def maybe_mark_paid
|
|
102
|
+
return unless amount_paid_changed?
|
|
103
|
+
if self.fully_paid? && self.may_mark_paid?
|
|
104
|
+
self.state_event = 'mark_paid'
|
|
105
|
+
elsif self.amount_paid > 0 && self.may_mark_partial?
|
|
106
|
+
self.state_event = 'mark_partial'
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def apply_balances
|
|
111
|
+
return unless amount_paid_changed?
|
|
112
|
+
change = amount_paid - amount_paid_was
|
|
113
|
+
|
|
114
|
+
Skr::Core.logger.debug "Applying payment #{amount_paid} changed: #{change}"
|
|
115
|
+
|
|
116
|
+
return if change.zero?
|
|
117
|
+
|
|
118
|
+
GlTransaction.push_or_save(
|
|
119
|
+
owner: self, amount: change,
|
|
120
|
+
debit: customer.gl_receivables_account, credit: GlAccount.default_for(:deposit_holding)
|
|
121
|
+
)
|
|
122
|
+
fire_event( :amount_paid_change )
|
|
123
|
+
true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def set_defaults
|
|
128
|
+
|
|
129
|
+
if pick_ticket
|
|
130
|
+
self.location = pick_ticket.location
|
|
131
|
+
self.sales_order = pick_ticket.sales_order
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if sales_order
|
|
135
|
+
self.terms ||= sales_order.terms
|
|
136
|
+
self.customer = sales_order.customer
|
|
137
|
+
self.po_num = sales_order.po_num if self.po_num.blank?
|
|
138
|
+
self.billing_address = sales_order.billing_address if self.billing_address.blank?
|
|
139
|
+
self.shipping_address = sales_order.shipping_address if self.shipping_address.blank?
|
|
140
|
+
self.options.merge!(sales_order.options)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
if customer
|
|
144
|
+
self.billing_address = customer.billing_address if self.billing_address.blank?
|
|
145
|
+
self.shipping_address = customer.shipping_address if self.shipping_address.blank?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def ensure_location_matches_so
|
|
151
|
+
if sales_order && location != sales_order.location
|
|
152
|
+
self.errors.add(:location, "#{location.code} must match location that order was taken on (#{sales_order.location.code})")
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
end # Skr module
|
data/lib/skr/location.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# A location that holds inventory
|
|
4
|
+
class Location < Skr::Model
|
|
5
|
+
|
|
6
|
+
has_code_identifier :from=>'name'
|
|
7
|
+
|
|
8
|
+
belongs_to :address, export: { writable: true }
|
|
9
|
+
|
|
10
|
+
has_many :sku_locs
|
|
11
|
+
|
|
12
|
+
validates :gl_branch_code, :presence => true, :numericality=>true, :length=>{:is=>2}
|
|
13
|
+
|
|
14
|
+
locked_fields :gl_branch_code
|
|
15
|
+
|
|
16
|
+
before_validation :set_defaults, :on=>:create
|
|
17
|
+
|
|
18
|
+
# @return [Location] the location that's specified by {Skr::Core::Configuration#default_location_code}
|
|
19
|
+
def self.default
|
|
20
|
+
Location.find_by_code( Core.config.default_location_code )
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def set_defaults
|
|
26
|
+
self.gl_branch_code ||= Skr::Core.config.default_branch_code
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/skr/model.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require_relative 'concerns/all'
|
|
2
|
+
|
|
3
|
+
module Skr
|
|
4
|
+
|
|
5
|
+
def self.table_name_prefix
|
|
6
|
+
Skr::Core.config.table_prefix
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Model < ::ActiveRecord::Base
|
|
11
|
+
self.abstract_class = true
|
|
12
|
+
|
|
13
|
+
include Concerns::Queries
|
|
14
|
+
include Concerns::PubSub
|
|
15
|
+
include Concerns::JsonAttributeAccess
|
|
16
|
+
include Concerns::TrackModifications
|
|
17
|
+
include Concerns::LockedFields
|
|
18
|
+
include Concerns::CodeIdentifier
|
|
19
|
+
include Concerns::RandomHashCode
|
|
20
|
+
include Concerns::VisibleIdIdentifier
|
|
21
|
+
|
|
22
|
+
include Concerns::ImmutableModel
|
|
23
|
+
include Concerns::ExportMethods
|
|
24
|
+
include Concerns::ExportScope
|
|
25
|
+
include Concerns::ExportAssociations
|
|
26
|
+
include Concerns::ExportJoinTables
|
|
27
|
+
include Concerns::SanitizeJson
|
|
28
|
+
include Concerns::ActsAsUOM
|
|
29
|
+
include Concerns::StateMachine
|
|
30
|
+
include Concerns::HasSkuLocLines
|
|
31
|
+
include Concerns::HasGlTransaction
|
|
32
|
+
include Concerns::IsOrderLike
|
|
33
|
+
include Concerns::IsSkuLocLine
|
|
34
|
+
include Concerns::AssociationExtensions
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# Implements the interface for a User model in Stockor
|
|
4
|
+
# This implementation grants access to everything
|
|
5
|
+
class NullUser
|
|
6
|
+
# Used to track created_by and updated_by
|
|
7
|
+
def id
|
|
8
|
+
0
|
|
9
|
+
end
|
|
10
|
+
# @param model [Skr::Model]
|
|
11
|
+
# @param attribute [Symbol]
|
|
12
|
+
# @return [Boolean] Can the User view the model?
|
|
13
|
+
def can_read?( model, attribute=nil)
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param model [Skr::Model]
|
|
18
|
+
# @param attribute [Symbol]
|
|
19
|
+
# @return [Boolean] Can the User create and update the model?
|
|
20
|
+
def can_write?(model, attribute=nil)
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @param model [Skr::Model]
|
|
25
|
+
# @return [Boolean] Can the User delete the model?
|
|
26
|
+
def can_delete?(type, model)
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
# A pay
|
|
4
|
+
class PaymentTerm < Skr::Model
|
|
5
|
+
|
|
6
|
+
has_code_identifier
|
|
7
|
+
|
|
8
|
+
def discount
|
|
9
|
+
@discount_percnum ||= Core::Numbers::PercNum.new( read_attribute('discount_amount') )
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def discount_amount=(value)
|
|
13
|
+
@discount_percnum = nil
|
|
14
|
+
super(value)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def immediate?
|
|
18
|
+
self.days.nil? || self.days.zero?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def discount_expires_at( start_date = Date.today )
|
|
22
|
+
( start_date + self.discount_days.days ).to_date
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def due_date_from( start_date = Date.today )
|
|
26
|
+
( start_date + self.days.days ).to_date
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
class PickTicket < Skr::Model
|
|
4
|
+
|
|
5
|
+
has_visible_id
|
|
6
|
+
is_order_like
|
|
7
|
+
|
|
8
|
+
belongs_to :sales_order
|
|
9
|
+
belongs_to :invoice, inverse_of: :pick_ticket, listen: { create: 'on_invoice' }
|
|
10
|
+
belongs_to :location
|
|
11
|
+
|
|
12
|
+
has_one :customer, through: :sales_order, export: true
|
|
13
|
+
has_one :terms, through: :sales_order
|
|
14
|
+
|
|
15
|
+
has_many :lines, ->{ order(:position) }, class_name: 'Skr::PtLine', inverse_of: :pick_ticket,
|
|
16
|
+
extend: Concerns::PT::Lines, export: { writable: true }
|
|
17
|
+
|
|
18
|
+
scope :with_details, lambda { | *args |
|
|
19
|
+
compose_query_using_detail_view( view: 'pt_details', join_to: 'pick_tickets_id' )
|
|
20
|
+
}, export: true
|
|
21
|
+
|
|
22
|
+
delegate :bill_addr, :to=>:sales_order
|
|
23
|
+
|
|
24
|
+
# If true, the PickTicket (and it's lines) will be marked as complete once it's saved
|
|
25
|
+
json_attr_accessor :mark_complete
|
|
26
|
+
|
|
27
|
+
before_update :check_for_mark_completed
|
|
28
|
+
|
|
29
|
+
validates :sales_order, set: true
|
|
30
|
+
validates :lines, presence: true
|
|
31
|
+
export_methods :ship_addr, :bill_addr
|
|
32
|
+
|
|
33
|
+
def ship_addr
|
|
34
|
+
sales_order.ship_addr.blank? ? sales_order.bill_addr : sales_order.ship_addr
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def is_tax_exempt?
|
|
38
|
+
self.sales_order.is_tax_exempt?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def is_other_charge_locked?
|
|
42
|
+
return is_complete
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cancel!
|
|
46
|
+
update_attributes({ :is_complete=> true })
|
|
47
|
+
lines.each do | line |
|
|
48
|
+
line.update_attributes :is_complete=>true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def check_for_mark_completed
|
|
55
|
+
return unless self.mark_complete
|
|
56
|
+
assign_attributes :is_complete=>true
|
|
57
|
+
lines.each do | line |
|
|
58
|
+
line.update_attributes :is_complete=>true
|
|
59
|
+
end
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def on_invoice(inv)
|
|
65
|
+
self.update_attributes is_complete: true, shipped_at: Time.now
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end # Skr module
|
data/lib/skr/po_line.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module Skr
|
|
2
|
+
|
|
3
|
+
class PoLine < Skr::Model
|
|
4
|
+
|
|
5
|
+
acts_as_uom
|
|
6
|
+
is_sku_loc_line parent: 'purchase_order'
|
|
7
|
+
|
|
8
|
+
belongs_to :purchase_order, :inverse_of=>:lines
|
|
9
|
+
belongs_to :sku_loc, export: true
|
|
10
|
+
belongs_to :sku_vendor, export: true
|
|
11
|
+
|
|
12
|
+
has_one :sku, :through => :sku_loc, export: true
|
|
13
|
+
|
|
14
|
+
has_many :receipts, class_name: 'Skr::PorLine',
|
|
15
|
+
:inverse_of=>:po_line, listen: { create: :update_qty_received! }
|
|
16
|
+
|
|
17
|
+
validates :purchase_order, :sku_loc, set: true
|
|
18
|
+
validates :description, :sku_code, presence: true
|
|
19
|
+
validates :qty, :price, numericality: true, allow_nil: false
|
|
20
|
+
|
|
21
|
+
locked_fields :qty, :qty_received
|
|
22
|
+
|
|
23
|
+
scope :incomplete, ->{ where('qty - qty_received - qty_canceled != 0' ) }
|
|
24
|
+
|
|
25
|
+
before_validation :set_defaults, :on=>:create
|
|
26
|
+
|
|
27
|
+
def qty_unreceived
|
|
28
|
+
qty - qty_received - qty_canceled
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def complete?
|
|
32
|
+
qty_unreceived.zero?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def update_qty_received!( receipt=nil )
|
|
36
|
+
unlock_fields :qty_received do
|
|
37
|
+
self.qty_received = receipts.sum(:qty)
|
|
38
|
+
self.save( :validate => false )
|
|
39
|
+
if self.complete?
|
|
40
|
+
self.purchase_order.set_maybe_completed!
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def set_defaults
|
|
48
|
+
if sku_loc && sku_vendor.nil?
|
|
49
|
+
self.sku_vendor = sku_loc.sku.sku_vendors.for_vendor( purchase_order.vendor )
|
|
50
|
+
elsif sku_vendor && sku_loc.nil?
|
|
51
|
+
self.sku_loc = sku_vendor.sku.sku_locs.find_or_create_for( purchase_order.location )
|
|
52
|
+
end
|
|
53
|
+
if sku_loc
|
|
54
|
+
self.sku_code ||= sku_loc.sku.code
|
|
55
|
+
self.description ||= sku_loc.sku.description
|
|
56
|
+
end
|
|
57
|
+
if sku_vendor
|
|
58
|
+
self.part_code ||= sku_vendor.part_code
|
|
59
|
+
self.price ||= sku_vendor.cost
|
|
60
|
+
self.uom_code ||= sku_vendor.uom_code
|
|
61
|
+
self.uom_size ||= sku_vendor.uom_size
|
|
62
|
+
end
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end # Skr module
|