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.
Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +6 -0
  4. data/Guardfile +13 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.md +88 -0
  7. data/Rakefile +58 -0
  8. data/config/database.yml +9 -0
  9. data/db/migrate/20120110142845_create_skr_sequential_ids.rb +35 -0
  10. data/db/migrate/20140202185309_create_skr_gl_accounts.rb +15 -0
  11. data/db/migrate/20140202193316_create_skr_gl_periods.rb +16 -0
  12. data/db/migrate/20140202193318_create_skr_gl_transactions.rb +14 -0
  13. data/db/migrate/20140202193319_create_skr_gl_postings.rb +16 -0
  14. data/db/migrate/20140202193700_create_skr_gl_manual_entries.rb +13 -0
  15. data/db/migrate/20140213040608_create_skr_payment_terms.rb +16 -0
  16. data/db/migrate/20140220031700_create_skr_addresses.rb +19 -0
  17. data/db/migrate/20140220031800_create_skr_locations.rb +19 -0
  18. data/db/migrate/20140220190836_create_skr_vendors.rb +22 -0
  19. data/db/migrate/20140220203029_create_skr_customers.rb +22 -0
  20. data/db/migrate/20140224034759_create_skr_skus.rb +22 -0
  21. data/db/migrate/20140225032853_create_skr_sku_locs.rb +21 -0
  22. data/db/migrate/20140320030501_create_skr_uoms.rb +19 -0
  23. data/db/migrate/20140321031604_create_skr_sku_vendors.rb +18 -0
  24. data/db/migrate/20140322012143_create_skr_ia_reasons.rb +14 -0
  25. data/db/migrate/20140322014401_create_skr_inventory_adjustments.rb +16 -0
  26. data/db/migrate/20140322023453_create_skr_ia_lines.rb +18 -0
  27. data/db/migrate/20140322035024_create_skr_sku_trans.rb +21 -0
  28. data/db/migrate/20140322223912_create_skr_sales_orders.rb +27 -0
  29. data/db/migrate/20140322223920_create_skr_so_lines.rb +25 -0
  30. data/db/migrate/20140323001446_create_so_details_view.rb +81 -0
  31. data/db/migrate/20140327202102_create_skr_purchase_orders.rb +20 -0
  32. data/db/migrate/20140327202107_create_skr_po_lines.rb +25 -0
  33. data/db/migrate/20140327202207_create_skr_pick_tickets.rb +16 -0
  34. data/db/migrate/20140327202209_create_skr_pt_lines.rb +23 -0
  35. data/db/migrate/20140327224000_create_skr_invoices.rb +25 -0
  36. data/db/migrate/20140327224002_create_skr_inv_lines.rb +23 -0
  37. data/db/migrate/20140330232808_create_skr_sku_loc_details_view.rb +31 -0
  38. data/db/migrate/20140330232810_create_skr_sku_qty_details_view.rb +48 -0
  39. data/db/migrate/20140400164729_create_skr_vouchers.rb +22 -0
  40. data/db/migrate/20140400164733_create_skr_vo_lines.rb +21 -0
  41. data/db/migrate/20140401164729_create_skr_po_receipt.rb +16 -0
  42. data/db/migrate/20140401164740_create_skr_por_line.rb +21 -0
  43. data/db/migrate/20140422024010_create_skr_inv_details_view.rb +42 -0
  44. data/lib/generators/stockor/migrations/install_generator.rb +42 -0
  45. data/lib/skr/address.rb +97 -0
  46. data/lib/skr/business_entity.rb +25 -0
  47. data/lib/skr/concerns/acts_as_uom.rb +47 -0
  48. data/lib/skr/concerns/all.rb +30 -0
  49. data/lib/skr/concerns/association_extensions.rb +85 -0
  50. data/lib/skr/concerns/attr_accessor_with_default.rb +54 -0
  51. data/lib/skr/concerns/code_identifier.rb +43 -0
  52. data/lib/skr/concerns/export_associations.rb +52 -0
  53. data/lib/skr/concerns/export_join_tables.rb +39 -0
  54. data/lib/skr/concerns/export_methods.rb +104 -0
  55. data/lib/skr/concerns/export_scope.rb +66 -0
  56. data/lib/skr/concerns/exported_limit_evaluator.rb +17 -0
  57. data/lib/skr/concerns/gl_tran_extensions.rb +18 -0
  58. data/lib/skr/concerns/has_gl_transaction.rb +67 -0
  59. data/lib/skr/concerns/has_sku_loc_lines.rb +47 -0
  60. data/lib/skr/concerns/immutable_model.rb +32 -0
  61. data/lib/skr/concerns/inv_extensions.rb +24 -0
  62. data/lib/skr/concerns/is_order_like.rb +47 -0
  63. data/lib/skr/concerns/is_sku_loc_line.rb +65 -0
  64. data/lib/skr/concerns/json_attribute_access.rb +55 -0
  65. data/lib/skr/concerns/locked_fields.rb +84 -0
  66. data/lib/skr/concerns/pt_extensions.rb +22 -0
  67. data/lib/skr/concerns/pub_sub.rb +105 -0
  68. data/lib/skr/concerns/queries.rb +20 -0
  69. data/lib/skr/concerns/random_hash_code.rb +40 -0
  70. data/lib/skr/concerns/sanitize_json.rb +49 -0
  71. data/lib/skr/concerns/sku_extensions.rb +52 -0
  72. data/lib/skr/concerns/so_extensions.rb +30 -0
  73. data/lib/skr/concerns/state_machine.rb +62 -0
  74. data/lib/skr/concerns/track_modifications.rb +48 -0
  75. data/lib/skr/concerns/visible_id_identifier.rb +53 -0
  76. data/lib/skr/core.rb +30 -0
  77. data/lib/skr/core/configuration.rb +87 -0
  78. data/lib/skr/core/db.rb +82 -0
  79. data/lib/skr/core/db/migration_helpers.rb +178 -0
  80. data/lib/skr/core/db/migrations.rb +15 -0
  81. data/lib/skr/core/db/seed.rb +46 -0
  82. data/lib/skr/core/db/seed/chart_of_accounts.yml +168 -0
  83. data/lib/skr/core/db/seed/payment_terms.yml +60 -0
  84. data/lib/skr/core/logger.rb +36 -0
  85. data/lib/skr/core/numbers.rb +71 -0
  86. data/lib/skr/core/rails_engine.rb +5 -0
  87. data/lib/skr/core/standard_pricing_provider.rb +15 -0
  88. data/lib/skr/core/strings.rb +57 -0
  89. data/lib/skr/core/testing.rb +11 -0
  90. data/lib/skr/core/testing/assertions.rb +44 -0
  91. data/lib/skr/core/testing/fixtures.rb +25 -0
  92. data/lib/skr/core/testing/fixtures/skr/addresses.yml +53 -0
  93. data/lib/skr/core/testing/fixtures/skr/customers.yml +43 -0
  94. data/lib/skr/core/testing/fixtures/skr/gl_accounts.yml +86 -0
  95. data/lib/skr/core/testing/fixtures/skr/gl_manual_entries.yml +4 -0
  96. data/lib/skr/core/testing/fixtures/skr/gl_periods.yml +26 -0
  97. data/lib/skr/core/testing/fixtures/skr/gl_postings.yml +88 -0
  98. data/lib/skr/core/testing/fixtures/skr/gl_transactions.yml +35 -0
  99. data/lib/skr/core/testing/fixtures/skr/ia_lines.yml +7 -0
  100. data/lib/skr/core/testing/fixtures/skr/ia_reasons.yml +15 -0
  101. data/lib/skr/core/testing/fixtures/skr/inv_lines.yml +22 -0
  102. data/lib/skr/core/testing/fixtures/skr/inventory_adjustments.yml +6 -0
  103. data/lib/skr/core/testing/fixtures/skr/invoices.yml +10 -0
  104. data/lib/skr/core/testing/fixtures/skr/locations.yml +24 -0
  105. data/lib/skr/core/testing/fixtures/skr/payment_terms.yml +42 -0
  106. data/lib/skr/core/testing/fixtures/skr/pick_tickets.yml +4 -0
  107. data/lib/skr/core/testing/fixtures/skr/po_lines.yml +44 -0
  108. data/lib/skr/core/testing/fixtures/skr/po_receipts.yml +5 -0
  109. data/lib/skr/core/testing/fixtures/skr/por_lines.yml +13 -0
  110. data/lib/skr/core/testing/fixtures/skr/pt_lines.yml +12 -0
  111. data/lib/skr/core/testing/fixtures/skr/purchase_orders.yml +16 -0
  112. data/lib/skr/core/testing/fixtures/skr/sales_orders.yml +32 -0
  113. data/lib/skr/core/testing/fixtures/skr/sku_locs.yml +78 -0
  114. data/lib/skr/core/testing/fixtures/skr/sku_trans.yml +9 -0
  115. data/lib/skr/core/testing/fixtures/skr/sku_vendors.yml +35 -0
  116. data/lib/skr/core/testing/fixtures/skr/skus.yml +50 -0
  117. data/lib/skr/core/testing/fixtures/skr/so_lines.yml +71 -0
  118. data/lib/skr/core/testing/fixtures/skr/uoms.yml +61 -0
  119. data/lib/skr/core/testing/fixtures/skr/vendors.yml +48 -0
  120. data/lib/skr/core/testing/fixtures/skr/vo_lines.yml +12 -0
  121. data/lib/skr/core/testing/fixtures/skr/vouchers.yml +8 -0
  122. data/lib/skr/core/testing/helper.rb +18 -0
  123. data/lib/skr/core/testing/test_case.rb +17 -0
  124. data/lib/skr/core/version.rb +5 -0
  125. data/lib/skr/customer.rb +34 -0
  126. data/lib/skr/gl_account.rb +56 -0
  127. data/lib/skr/gl_manual_entry.rb +31 -0
  128. data/lib/skr/gl_period.rb +13 -0
  129. data/lib/skr/gl_posting.rb +54 -0
  130. data/lib/skr/gl_transaction.rb +174 -0
  131. data/lib/skr/ia_line.rb +129 -0
  132. data/lib/skr/ia_reason.rb +16 -0
  133. data/lib/skr/inv_line.rb +90 -0
  134. data/lib/skr/inventory_adjustment.rb +60 -0
  135. data/lib/skr/invoice.rb +159 -0
  136. data/lib/skr/location.rb +31 -0
  137. data/lib/skr/model.rb +37 -0
  138. data/lib/skr/null_user.rb +30 -0
  139. data/lib/skr/payment_term.rb +30 -0
  140. data/lib/skr/pick_ticket.rb +71 -0
  141. data/lib/skr/po_line.rb +69 -0
  142. data/lib/skr/po_receipt.rb +51 -0
  143. data/lib/skr/por_line.rb +80 -0
  144. data/lib/skr/pt_line.rb +74 -0
  145. data/lib/skr/purchase_order.rb +112 -0
  146. data/lib/skr/sales_order.rb +159 -0
  147. data/lib/skr/sequential_id.rb +23 -0
  148. data/lib/skr/sku.rb +99 -0
  149. data/lib/skr/sku_loc.rb +94 -0
  150. data/lib/skr/sku_tran.rb +111 -0
  151. data/lib/skr/sku_vendor.rb +26 -0
  152. data/lib/skr/so_line.rb +159 -0
  153. data/lib/skr/uom.rb +63 -0
  154. data/lib/skr/user_proxy.rb +60 -0
  155. data/lib/skr/validators/all.rb +2 -0
  156. data/lib/skr/validators/email.rb +17 -0
  157. data/lib/skr/validators/set.rb +18 -0
  158. data/lib/skr/vendor.rb +33 -0
  159. data/lib/skr/vo_line.rb +35 -0
  160. data/lib/skr/voucher.rb +119 -0
  161. data/lib/stockor/core.rb +9 -0
  162. data/stockor-core.gemspec +37 -0
  163. data/tasks/migrations.rake +23 -0
  164. data/tasks/publish.rake +8 -0
  165. data/test/address_test.rb +57 -0
  166. data/test/concerns/attr_with_default_test.rb +45 -0
  167. data/test/concerns/code_identifier_test.rb +46 -0
  168. data/test/concerns/export_associations_test.rb +7 -0
  169. data/test/concerns/export_methods_test.rb +31 -0
  170. data/test/concerns/export_scope_test.rb +16 -0
  171. data/test/concerns/exported_limits_test.rb +47 -0
  172. data/test/concerns/json_attribute_access_test.rb +27 -0
  173. data/test/concerns/pub_sub_test.rb +83 -0
  174. data/test/concerns/sanitize_json_test.rb +47 -0
  175. data/test/core/configuration_test.rb +24 -0
  176. data/test/core/numbers_test.rb +26 -0
  177. data/test/core/strings_test.rb +41 -0
  178. data/test/customer_test.rb +34 -0
  179. data/test/gl_account_test.rb +23 -0
  180. data/test/gl_manual_entry_test.rb +17 -0
  181. data/test/gl_period_test.rb +12 -0
  182. data/test/gl_posting_test.rb +39 -0
  183. data/test/gl_transaction_test.rb +58 -0
  184. data/test/ia_line_test.rb +68 -0
  185. data/test/ia_reason_test.rb +11 -0
  186. data/test/inv_line_test.rb +58 -0
  187. data/test/inventory_adjustment_test.rb +72 -0
  188. data/test/invoice_test.rb +63 -0
  189. data/test/location_test.rb +10 -0
  190. data/test/payment_term_test.rb +25 -0
  191. data/test/pick_ticket_test.rb +27 -0
  192. data/test/po_line_test.rb +36 -0
  193. data/test/po_receipt_test.rb +93 -0
  194. data/test/por_line_test.rb +79 -0
  195. data/test/pt_line_test.rb +29 -0
  196. data/test/purchase_order_test.rb +44 -0
  197. data/test/sales_order_test.rb +74 -0
  198. data/test/sku_loc_test.rb +50 -0
  199. data/test/sku_test.rb +45 -0
  200. data/test/sku_tran_test.rb +21 -0
  201. data/test/sku_vendor_test.rb +13 -0
  202. data/test/so_line_test.rb +89 -0
  203. data/test/test_helper.rb +1 -0
  204. data/test/uom_test.rb +14 -0
  205. data/test/vendor_test.rb +35 -0
  206. data/test/vo_line_test.rb +20 -0
  207. data/test/voucher_test.rb +35 -0
  208. data/yard_ext/all.rb +9 -0
  209. data/yard_ext/code_identifier_handler.rb +33 -0
  210. data/yard_ext/concern_meta_methods.rb +60 -0
  211. data/yard_ext/config_options.rb +27 -0
  212. data/yard_ext/exported_scope.rb +4 -0
  213. data/yard_ext/immutable_handler.rb +17 -0
  214. data/yard_ext/json_attr_accessor.rb +22 -0
  215. data/yard_ext/locked_fields_handler.rb +21 -0
  216. data/yard_ext/templates/default/layout/html/layout.erb +20 -0
  217. data/yard_ext/templates/default/method_details/html/github_link.erb +1 -0
  218. data/yard_ext/templates/default/method_details/setup.rb +3 -0
  219. data/yard_ext/validators.rb +1 -0
  220. data/yard_ext/visible_id_handler.rb +38 -0
  221. 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
@@ -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
@@ -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
@@ -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