stockor 0.1.9 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (313) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +254 -72
  4. data/Guardfile +1 -1
  5. data/README.md +24 -3
  6. data/app.json +28 -0
  7. data/client/skr/Extension.coffee +18 -0
  8. data/client/skr/components/BankAccountFinder.cjsx +34 -0
  9. data/client/skr/components/Currency.cjsx +19 -0
  10. data/client/skr/components/CustomerFinder.cjsx +37 -0
  11. data/client/skr/components/CustomerLink.cjsx +13 -0
  12. data/client/skr/components/CustomerProjectFinder.cjsx +49 -0
  13. data/client/skr/components/GlAccountChooser.cjsx +38 -0
  14. data/client/skr/components/InvoiceFinder.cjsx +37 -0
  15. data/client/skr/components/InvoiceLink.cjsx +13 -0
  16. data/client/skr/components/LocationChooser.cjsx +37 -0
  17. data/client/skr/components/PaymentCategoryFinder.cjsx +34 -0
  18. data/client/skr/components/PrintFormChooser.cjsx +29 -0
  19. data/client/skr/components/SalesOrderFinder.cjsx +38 -0
  20. data/client/skr/components/ScreenControls.cjsx +20 -0
  21. data/client/skr/components/SkuFinder.cjsx +30 -0
  22. data/client/skr/components/SkuLines.cjsx +76 -0
  23. data/client/skr/components/SystemSettings.cjsx +26 -0
  24. data/client/skr/components/TermsChooser.cjsx +40 -0
  25. data/client/skr/components/ToolbarButton.cjsx +7 -0
  26. data/client/skr/components/TotalsLine.cjsx +21 -0
  27. data/client/skr/components/TriStateIcon.cjsx +12 -0
  28. data/client/skr/components/UOMChooser.cjsx +24 -0
  29. data/client/skr/components/UserPreferences.cjsx +30 -0
  30. data/client/skr/components/VendorFinder.cjsx +40 -0
  31. data/client/skr/components/address/Address.cjsx +10 -10
  32. data/client/skr/components/styles.scss +16 -0
  33. data/client/skr/index.js +3 -1
  34. data/client/skr/models/Address.coffee +9 -1
  35. data/client/skr/models/BankAccount.coffee +17 -0
  36. data/client/skr/models/Base.coffee +6 -0
  37. data/client/skr/models/Customer.coffee +17 -10
  38. data/client/skr/models/CustomerProject.coffee +29 -0
  39. data/client/skr/models/GlAccount.coffee +22 -10
  40. data/client/skr/models/GlManualEntry.coffee +4 -2
  41. data/client/skr/models/GlPeriod.coffee +4 -6
  42. data/client/skr/models/GlPosting.coffee +7 -7
  43. data/client/skr/models/GlTransaction.coffee +3 -3
  44. data/client/skr/models/IaLine.coffee +9 -9
  45. data/client/skr/models/IaReason.coffee +4 -4
  46. data/client/skr/models/InvLine.coffee +30 -11
  47. data/client/skr/models/InventoryAdjustment.coffee +8 -6
  48. data/client/skr/models/Invoice.coffee +89 -18
  49. data/client/skr/models/Location.coffee +27 -6
  50. data/client/skr/models/Payment.coffee +36 -0
  51. data/client/skr/models/PaymentCategory.coffee +12 -0
  52. data/client/skr/models/PaymentTerm.coffee +17 -4
  53. data/client/skr/models/PickTicket.coffee +7 -5
  54. data/client/skr/models/PoLine.coffee +15 -15
  55. data/client/skr/models/PoReceipt.coffee +8 -6
  56. data/client/skr/models/PorLine.coffee +11 -11
  57. data/client/skr/models/PricingProvider.coffee +6 -0
  58. data/client/skr/models/PtLine.coffee +13 -13
  59. data/client/skr/models/PurchaseOrder.coffee +11 -9
  60. data/client/skr/models/SalesOrder.coffee +59 -22
  61. data/client/skr/models/Sku.coffee +17 -15
  62. data/client/skr/models/SkuLoc.coffee +14 -9
  63. data/client/skr/models/SkuTran.coffee +10 -10
  64. data/client/skr/models/SkuVendor.coffee +9 -9
  65. data/client/skr/models/SoLine.coffee +27 -20
  66. data/client/skr/models/TimeEntry.coffee +75 -0
  67. data/client/skr/models/Uom.coffee +27 -6
  68. data/client/skr/models/Vendor.coffee +14 -12
  69. data/client/skr/models/VoLine.coffee +11 -11
  70. data/client/skr/models/Voucher.coffee +7 -5
  71. data/client/skr/models/mixins/HasVisibleId.coffee +7 -0
  72. data/client/skr/models/mixins/PrintSupport.coffee +6 -0
  73. data/client/skr/models/mixins/SkuLine.coffee +61 -0
  74. data/client/skr/screens/Commands.coffee +29 -0
  75. data/client/skr/screens/bank-maint/BankMaint.cjsx +43 -0
  76. data/client/skr/screens/bank-maint/index.js +5 -0
  77. data/client/skr/screens/chart-of-accounts/ChartOfAccounts.cjsx +40 -0
  78. data/client/skr/screens/chart-of-accounts/index.js +1 -0
  79. data/client/skr/screens/chart-of-accounts/index.scss +12 -0
  80. data/client/skr/screens/customer-maint/CustomerMaint.cjsx +35 -36
  81. data/client/skr/screens/customer-projects/CustomerProjects.cjsx +70 -0
  82. data/client/skr/screens/customer-projects/index.js +5 -0
  83. data/client/skr/screens/customer-projects/index.scss +25 -0
  84. data/client/skr/screens/fresh-books-import/ApiInfo.cjsx +35 -0
  85. data/client/skr/screens/fresh-books-import/ChooseRecords.cjsx +116 -0
  86. data/client/skr/screens/fresh-books-import/FreshBooksImport.cjsx +31 -0
  87. data/client/skr/screens/fresh-books-import/Import.coffee +52 -0
  88. data/client/skr/screens/fresh-books-import/ViewRecords.cjsx +96 -0
  89. data/client/skr/screens/fresh-books-import/index.js +1 -0
  90. data/client/skr/screens/fresh-books-import/index.scss +39 -0
  91. data/client/skr/screens/gl-accounts/GlAccounts.cjsx +31 -0
  92. data/client/skr/screens/gl-accounts/index.js +5 -0
  93. data/client/skr/screens/gl-transactions/GlTransactions.cjsx +46 -0
  94. data/client/skr/screens/gl-transactions/index.js +1 -0
  95. data/client/skr/screens/gl-transactions/index.scss +12 -0
  96. data/client/skr/screens/invoice/Invoice.cjsx +92 -0
  97. data/client/skr/screens/invoice/Payment.cjsx +28 -0
  98. data/client/skr/screens/invoice/index.js +5 -0
  99. data/client/skr/screens/locations/Locations.cjsx +31 -0
  100. data/client/skr/screens/locations/index.js +5 -0
  101. data/client/skr/screens/payment-category/PaymentCategory.cjsx +28 -0
  102. data/client/skr/screens/payment-category/index.js +5 -0
  103. data/client/skr/screens/payment-category/index.scss +9 -0
  104. data/client/skr/screens/payment-terms/PaymentTerms.cjsx +28 -0
  105. data/client/skr/screens/payment-terms/index.js +5 -0
  106. data/client/skr/screens/payment-terms/index.scss +9 -0
  107. data/client/skr/screens/payments/Payments.cjsx +59 -0
  108. data/client/skr/screens/payments/index.js +5 -0
  109. data/client/skr/screens/sales-order/SalesOrder.cjsx +68 -0
  110. data/client/skr/screens/sales-order/index.js +1 -5
  111. data/client/skr/screens/sku-maint/SkuMaint.cjsx +53 -0
  112. data/client/skr/screens/sku-maint/SkuUomList.cjsx +209 -0
  113. data/client/skr/screens/sku-maint/index.js +2 -5
  114. data/client/skr/screens/sku-maint/index.scss +37 -6
  115. data/client/skr/screens/time-invoicing/TimeInvoicing.cjsx +156 -0
  116. data/client/skr/screens/time-invoicing/index.js +5 -0
  117. data/client/skr/screens/time-invoicing/index.scss +7 -0
  118. data/client/skr/screens/time-tracking/EditEntry.cjsx +54 -0
  119. data/client/skr/screens/time-tracking/Entries.coffee +132 -0
  120. data/client/skr/screens/time-tracking/Header.cjsx +71 -0
  121. data/client/skr/screens/time-tracking/Popover.cjsx +70 -0
  122. data/client/skr/screens/time-tracking/PopoverMiniControls.cjsx +25 -0
  123. data/client/skr/screens/time-tracking/TimeTracking.cjsx +63 -0
  124. data/client/skr/screens/time-tracking/WeekSummary.cjsx +16 -0
  125. data/client/skr/screens/time-tracking/index.js +1 -0
  126. data/client/skr/screens/time-tracking/index.scss +126 -0
  127. data/client/skr/screens/vendor-maint/VendorMaint.cjsx +45 -0
  128. data/client/skr/screens/vendor-maint/index.js +1 -5
  129. data/client/skr/styles.scss +1 -13
  130. data/config/puma.rb +4 -0
  131. data/config/routes.rb +21 -9
  132. data/config/screens.rb +147 -32
  133. data/db/migrate/20140202194700_create_skr_gl_transaction_details.rb +35 -0
  134. data/db/migrate/20140220031800_create_skr_locations.rb +2 -0
  135. data/db/migrate/20140220190836_create_skr_vendors.rb +1 -0
  136. data/db/migrate/20140220203029_create_skr_customers.rb +3 -2
  137. data/db/migrate/20140224034759_create_skr_skus.rb +2 -3
  138. data/db/migrate/20140322223912_create_skr_sales_orders.rb +4 -3
  139. data/db/migrate/20140322223920_create_skr_so_lines.rb +4 -5
  140. data/db/migrate/20140323001446_create_so_details_view.rb +7 -5
  141. data/db/migrate/20140327202209_create_skr_pt_lines.rb +2 -2
  142. data/db/migrate/20140327214000_create_customer_project.rb +16 -0
  143. data/db/migrate/20140327223002_create_time_entries.rb +17 -0
  144. data/db/migrate/20140327224000_create_skr_invoices.rb +5 -1
  145. data/db/migrate/20140327224002_create_skr_inv_lines.rb +3 -1
  146. data/db/migrate/20140422024010_create_skr_inv_details_view.rb +1 -1
  147. data/db/migrate/20151121211323_create_customer_project_details_views.rb +31 -0
  148. data/db/migrate/20160216142845_create_gl_account_balances_view.rb +20 -0
  149. data/db/migrate/20160229002044_create_bank_accounts.rb +18 -0
  150. data/db/migrate/20160229041711_create_payments.rb +33 -0
  151. data/db/migrate/20160307022705_create_create_combined_uom_views.rb +18 -0
  152. data/db/schema.sql +639 -140
  153. data/db/seed/chart_of_accounts.yml +8 -6
  154. data/db/seed/payment_categories.yml +12 -0
  155. data/db/seed/skus.yml +32 -0
  156. data/db/seed.rb +21 -0
  157. data/lib/skr/access_roles.rb +19 -6
  158. data/lib/skr/concerns/has_sku_loc_lines.rb +0 -16
  159. data/lib/skr/concerns/inv_extensions.rb +24 -0
  160. data/lib/skr/concerns/is_sku_loc_line.rb +3 -4
  161. data/lib/skr/concerns/so_extensions.rb +8 -0
  162. data/lib/skr/concerns/visible_id_identifier.rb +1 -1
  163. data/lib/skr/db/migration_helpers.rb +2 -4
  164. data/lib/skr/extension.rb +11 -4
  165. data/lib/skr/handlers/fresh_books_import.rb +20 -0
  166. data/lib/skr/handlers/invoice_from_time_entries.rb +49 -0
  167. data/lib/skr/jobs/fresh_books/base.rb +54 -0
  168. data/lib/skr/jobs/fresh_books/import.rb +151 -0
  169. data/lib/skr/jobs/fresh_books/retrieve.rb +62 -0
  170. data/lib/skr/model.rb +5 -0
  171. data/lib/skr/models/address.rb +1 -1
  172. data/lib/skr/models/bank_account.rb +13 -0
  173. data/lib/skr/models/business_entity.rb +3 -0
  174. data/lib/skr/models/customer.rb +1 -1
  175. data/lib/skr/models/customer_project.rb +22 -0
  176. data/lib/skr/models/gl_account.rb +13 -3
  177. data/lib/skr/models/gl_period.rb +6 -0
  178. data/lib/skr/models/gl_posting.rb +7 -4
  179. data/lib/skr/models/gl_transaction.rb +19 -33
  180. data/lib/skr/models/ia_line.rb +1 -1
  181. data/lib/skr/models/inv_line.rb +33 -15
  182. data/lib/skr/models/invoice.rb +47 -20
  183. data/lib/skr/models/location.rb +7 -1
  184. data/lib/skr/models/payment.rb +49 -0
  185. data/lib/skr/models/payment_category.rb +11 -0
  186. data/lib/skr/models/payment_term.rb +1 -1
  187. data/lib/skr/models/por_line.rb +1 -1
  188. data/lib/skr/models/pt_line.rb +1 -1
  189. data/lib/skr/models/sales_order.rb +9 -9
  190. data/lib/skr/models/sku_loc.rb +1 -1
  191. data/lib/skr/models/sku_tran.rb +6 -11
  192. data/lib/skr/models/so_line.rb +22 -12
  193. data/lib/skr/models/time_entry.rb +36 -0
  194. data/lib/skr/models/uom.rb +11 -10
  195. data/lib/skr/models/user_proxy.rb +1 -1
  196. data/lib/skr/number.rb +25 -0
  197. data/lib/skr/print/form.rb +46 -0
  198. data/lib/skr/print/template.rb +48 -0
  199. data/lib/skr/print.rb +11 -0
  200. data/lib/skr/string.rb +11 -0
  201. data/lib/skr/version.rb +1 -1
  202. data/lib/skr.rb +9 -0
  203. data/spec/fixtures/skr/address.yml +164 -4
  204. data/spec/fixtures/skr/bank_account.yml +8 -0
  205. data/spec/fixtures/skr/customer.yml +30 -4
  206. data/spec/fixtures/skr/customer_project.yml +20 -0
  207. data/spec/fixtures/skr/gl_account.yml +19 -1
  208. data/spec/fixtures/skr/gl_period.yml +3 -0
  209. data/spec/fixtures/skr/gl_posting.yml +22 -1
  210. data/spec/fixtures/skr/gl_transaction.yml +4 -1
  211. data/spec/fixtures/skr/inv_line.yml +35 -0
  212. data/spec/fixtures/skr/invoice.yml +13 -2
  213. data/spec/fixtures/skr/location.yml +5 -0
  214. data/spec/fixtures/skr/payment.yml +10 -0
  215. data/spec/fixtures/skr/payment_category.yml +8 -0
  216. data/spec/fixtures/skr/payment_term.yml +37 -3
  217. data/spec/fixtures/skr/sales_order.yml +12 -1
  218. data/spec/fixtures/skr/sku.yml +78 -1
  219. data/spec/fixtures/skr/sku_loc.yml +42 -1
  220. data/spec/fixtures/skr/sku_tran.yml +24 -1
  221. data/spec/fixtures/skr/so_line.yml +32 -0
  222. data/spec/fixtures/skr/time_entry.yml +82 -0
  223. data/spec/fixtures/skr/uom.yml +52 -1
  224. data/spec/fixtures/skr/vendor.yml +28 -1
  225. data/spec/fixtures/stockor.png +0 -0
  226. data/spec/server/bank_account_spec.rb +10 -0
  227. data/spec/server/customer_project_spec.rb +10 -0
  228. data/spec/server/handlers/invoice_from_time_entries_spec.rb +49 -0
  229. data/spec/server/jobs/fresh_books/import_spec.rb +69 -0
  230. data/spec/server/jobs/fresh_books/retrieve_spec.rb +37 -0
  231. data/spec/server/models/address_spec.rb +4 -3
  232. data/spec/server/models/gl_transaction_spec.rb +3 -3
  233. data/spec/server/models/inv_line_spec.rb +83 -3
  234. data/spec/server/models/invoice_spec.rb +32 -3
  235. data/spec/server/models/payment_spec.rb +40 -0
  236. data/spec/server/models/sales_order_spec.rb +1 -1
  237. data/spec/server/models/so_line_spec.rb +3 -3
  238. data/spec/server/models/spec_helper_spec.rb +1 -1
  239. data/spec/server/payment_spec.rb +10 -0
  240. data/spec/server/print/form_spec.rb +47 -0
  241. data/spec/server/print/template_spec.rb +36 -0
  242. data/spec/server/spec_helper.rb +14 -1
  243. data/spec/server/time_entry_spec.rb +10 -0
  244. data/spec/skr/components/SkuLinesSpec.coffee +61 -0
  245. data/spec/skr/models/BankAccountSpec.coffee +5 -0
  246. data/spec/skr/models/CustomerProjectSpec.coffee +5 -0
  247. data/spec/skr/models/CustomerSpec.coffee +2 -2
  248. data/spec/skr/models/PaymentSpec.coffee +5 -0
  249. data/spec/skr/models/SalesOrderSpec.coffee +21 -5
  250. data/spec/skr/models/SoLineSpec.coffee +7 -2
  251. data/spec/skr/models/TimeEntrySpec.coffee +5 -0
  252. data/spec/skr/screens/bank-maint/BankMaintSpec.coffee +5 -0
  253. data/spec/skr/screens/customer-projects/CustomerProjectsSpec.coffee +5 -0
  254. data/spec/skr/screens/fresh-books-import/FreshBooksImportSpec.coffee +1 -0
  255. data/spec/skr/screens/gl-accounts/GlAccountsSpec.coffee +5 -0
  256. data/spec/skr/screens/invoice/InvoiceSpec.coffee +5 -0
  257. data/spec/skr/screens/locations/LocationsSpec.coffee +5 -0
  258. data/spec/skr/screens/payment-category/PaymentCategorySpec.coffee +5 -0
  259. data/spec/skr/screens/payment-terms/PaymentTermsSpec.coffee +5 -0
  260. data/spec/skr/screens/payments/PaymentsSpec.coffee +5 -0
  261. data/spec/skr/screens/time-invoicing/TimeInvoicingSpec.coffee +5 -0
  262. data/spec/skr/screens/time-tracking/TimeTrackingSpec.coffee +14 -0
  263. data/spec/vcr/freshbooks.yml +698 -0
  264. data/stockor.gemspec +5 -1
  265. data/templates/print/fonts/GnuMICR.otf +0 -0
  266. data/templates/print/layout.tex.erb +39 -0
  267. data/templates/print/packages/booktabs.sty +182 -0
  268. data/templates/print/packages/fancybox.sty +966 -0
  269. data/templates/print/packages/fancyhdr.sty +485 -0
  270. data/templates/print/packages/graphbox.sty +129 -0
  271. data/templates/print/packages/lastpage.sty +283 -0
  272. data/templates/print/packages/lastpage209.sty +70 -0
  273. data/templates/print/packages/marginnote.sty +412 -0
  274. data/templates/print/packages/multirow.sty +159 -0
  275. data/templates/print/packages/rotating.sty +282 -0
  276. data/templates/print/packages/tabu.sty +2557 -0
  277. data/templates/print/packages/textpos.sty +361 -0
  278. data/templates/print/packages/varwidth.sty +318 -0
  279. data/templates/print/partials/address.tex.erb +6 -0
  280. data/templates/print/partials/bill_to_ship_to.tex.erb +13 -0
  281. data/templates/print/partials/header.tex.erb +13 -0
  282. data/templates/print/partials/invoice_paid_state.tex.erb +2 -0
  283. data/templates/print/partials/old/inv_lines_grouping.tex.erb +8 -0
  284. data/templates/print/partials/old/labor_lines_footer.tex.erb +18 -0
  285. data/templates/print/partials/skus_table.tex.erb +32 -0
  286. data/templates/print/partials/skus_table_col_hdr.tex.erb +8 -0
  287. data/templates/print/partials/skus_table_footer.tex.erb +5 -0
  288. data/templates/print/partials/skus_table_group_footer.tex.erb +4 -0
  289. data/templates/print/partials/skus_table_invoice_footer.tex.erb +25 -0
  290. data/templates/print/partials/skus_table_invoice_info_line.tex.erb +16 -0
  291. data/templates/print/partials/skus_table_labor_col_hdr.tex.erb +8 -0
  292. data/templates/print/partials/skus_table_labor_group_footer.tex.erb +7 -0
  293. data/templates/print/partials/skus_table_labor_line.tex.erb +11 -0
  294. data/templates/print/partials/skus_table_line.tex.erb +6 -0
  295. data/templates/print/partials/skus_table_other_charge_lines.tex.erb +7 -0
  296. data/templates/print/partials/so_info_line.tex.erb +14 -0
  297. data/templates/print/types/invoice/default.tex.erb +13 -0
  298. data/templates/print/types/invoice/labor.tex.erb +33 -0
  299. data/templates/print/types/payment/default.tex.erb +64 -0
  300. data/templates/print/types/sales-order/default.tex.erb +8 -0
  301. metadata +252 -15
  302. data/client/skr/components/address/address.html +0 -20
  303. data/client/skr/models/mixins/CodeField.coffee +0 -5
  304. data/client/skr/screens/customer-maint/index.scss +0 -11
  305. data/client/skr/screens/customer-maint/layout.html +0 -32
  306. data/client/skr/screens/sales-order/SalesOrder.coffee +0 -30
  307. data/client/skr/screens/sales-order/index.scss +0 -8
  308. data/client/skr/screens/sales-order/layout.html +0 -30
  309. data/client/skr/screens/sku-maint/SkuMaint.coffee +0 -18
  310. data/client/skr/screens/sku-maint/layout.html +0 -16
  311. data/client/skr/screens/vendor-maint/VendorMaint.coffee +0 -28
  312. data/client/skr/screens/vendor-maint/index.scss +0 -8
  313. data/client/skr/screens/vendor-maint/layout.html +0 -32
@@ -85,7 +85,7 @@ module Skr
85
85
  ret << ', ' + postal_code.to_s unless postal_code.blank?
86
86
  include = [ *include ]
87
87
  if include.any?
88
- ret << "\n" + include.map{ | field | self[ field ] }.join(' ')
88
+ ret << "\n" + include.map{ | field | self[ field ] }.join("\n")
89
89
  end
90
90
  ret
91
91
  end
@@ -0,0 +1,13 @@
1
+ module Skr
2
+
3
+ class BankAccount < Model
4
+
5
+ has_code_identifier from: 'name'
6
+
7
+ belongs_to :gl_account, class_name: 'Skr::GlAccount', export: true
8
+
9
+ belongs_to :address, class_name: 'Skr::Address',
10
+ export: { writable: true }, dependent: :destroy
11
+ end
12
+
13
+ end
@@ -26,6 +26,9 @@ module Skr
26
26
  self.terms ||= PaymentTerm.find_by_code(Skr.config.customer_terms_code)
27
27
  end
28
28
 
29
+ def get_form(type)
30
+ forms ? forms[type] : 'default'
31
+ end
29
32
  end
30
33
 
31
34
  end
@@ -21,7 +21,7 @@ module Skr
21
21
  # Updates the amount the customer owes, which is the sum of the amount unpaid on open invoices
22
22
  def update_balance!(*)
23
23
  update_attributes open_balance: invoices.open_for_customer(self)
24
- .with_details.sum('details.total')
24
+ .with_details.sum('details.invoice_total')
25
25
  end
26
26
 
27
27
  private
@@ -0,0 +1,22 @@
1
+ module Skr
2
+
3
+ class CustomerProject < Model
4
+ has_code_identifier from: 'name'
5
+
6
+ belongs_to :sku, export: true
7
+ belongs_to :customer, export: true
8
+
9
+ delegate_and_export :sku_code
10
+ delegate_and_export :customer_code
11
+
12
+ validates :sku, :customer, set: true
13
+
14
+ has_many :time_entries, inverse_of: :customer_project, export: true
15
+
16
+ scope :with_details, lambda { | *args |
17
+ compose_query_using_detail_view(view: 'skr_customer_project_details')
18
+ }, export: true
19
+
20
+ end
21
+
22
+ end
@@ -10,7 +10,17 @@ module Skr
10
10
 
11
11
  is_immutable except: [:name, :is_active]
12
12
 
13
- validates :name, :description, :presence => true
13
+ validates :name, :presence => true
14
+
15
+ # joins the gl_balances view which includes the
16
+ # branch_number and balance fields
17
+ scope :with_balances, lambda { | *args |
18
+ compose_query_using_detail_view(view: 'skr_gl_account_balances')
19
+ }, export: true
20
+
21
+ scope :with_combined_name, lambda {|*args|
22
+ select("*, number||' '||name as combined_name")
23
+ }, export: true
14
24
 
15
25
  # @!attribute description
16
26
  # A short description of the GL Account
@@ -19,7 +29,7 @@ module Skr
19
29
  # with mandatory 4 characters + 2 char branch code
20
30
  validates :number, :presence => true, :numericality=>true, :length=>{ :is=>4 }
21
31
 
22
- # @return [GlAccount] the default account for the key from {Skr::Core::Configuration.default_gl_accounts}
32
+ # @return [GlAccount] the default account for the key from {Skr::Configuration.default_gl_accounts}
23
33
  def self.default_for( lookup )
24
34
  number = Skr.config.default_gl_accounts[ lookup ]
25
35
  raise RuntimeError.new("Unkown GL default account lookup code: {lookup}") unless number
@@ -48,7 +58,7 @@ module Skr
48
58
 
49
59
  # @return [BigDecimal] the balance for a given period
50
60
  def balance_for( period, mask = self.account_mask )
51
- GlPosting.matching( period, account_mask ).sum(:amount)
61
+ GlPosting.applying_to_period( period ).matching( account_mask ).sum(:amount)
52
62
  end
53
63
 
54
64
  end
@@ -8,6 +8,12 @@ module Skr
8
8
  attr = { year: Time.now.year, period: Time.now.month }
9
9
  GlPeriod.where( attr ).first || GlPeriod.create( attr )
10
10
  end
11
+
12
+ def self.is_date_locked?( date )
13
+ date && GlPeriod.select(:is_locked).where(
14
+ year: date.year, period: date.month, is_locked: true
15
+ ).first
16
+ end
11
17
  end
12
18
 
13
19
  end
@@ -12,10 +12,13 @@ module Skr
12
12
  validates :amount, numericality: true, presence: true
13
13
  validate :ensure_accounting_validity, on: :create
14
14
 
15
- scope :applying_to_period, ->(period){ where( '(period <= :period and year = :year) or (year < :year)',
16
- { period: period.period, year: period.year } ) }
17
- scope :matching, ->(period, account_mask){
18
- applying_to_period( period ).where('account_number like ?', account_mask )
15
+ scope :applying_to_period, -> (period) {
16
+ where( '(period <= :period and year = :year) or (year < :year)',
17
+ { period: period.period, year: period.year } )
18
+ }
19
+
20
+ scope :matching, -> (account_mask) {
21
+ where('account_number like ?', account_mask )
19
22
  }
20
23
 
21
24
  def account=(acct)
@@ -1,4 +1,3 @@
1
-
2
1
  module Skr
3
2
 
4
3
  # A transaction is a record of a business event that has financial consequences.
@@ -20,12 +19,16 @@ module Skr
20
19
 
21
20
  is_immutable
22
21
 
23
- # A Transaction must refer to another record, such as Invoice, Inventory Adjustment, or a Manual Posting.
22
+ # A Transaction must refer to another record,
23
+ # such as Invoice, Inventory Adjustment, or a Manual Posting.
24
24
  belongs_to :source, :polymorphic=>true
25
25
 
26
26
  # Each transaction belongs to an accounting period
27
27
  belongs_to :period, :class_name=>'Skr::GlPeriod', export: true
28
28
 
29
+ has_many :postings, class_name: 'Skr::GlPosting',
30
+ inverse_of: :gl_transaction, export: { writable: true }
31
+
29
32
  has_many :credits, ->{ where({ is_debit: false }) }, class_name: 'Skr::GlPosting',
30
33
  extend: Concerns::GlTran::Postings,
31
34
  inverse_of: :gl_transaction, export: { writable: true }
@@ -40,17 +43,22 @@ module Skr
40
43
  validates :source, :period, :set=>true
41
44
  validates :description, :presence=>true
42
45
 
46
+ scope :with_details, lambda { | acct = nil |
47
+ query = compose_query_using_detail_view(view: 'skr_gl_transaction_details',
48
+ join_to: :gl_transaction_id)
49
+ acct.blank? ? query : query.joins(:postings).merge( GlPosting.matching(acct) )
50
+ }, export: true
43
51
 
44
52
  # Add a debit/credit pair to the transaction with amount
45
53
  # @param amount [BigDecimal] the amount to apply to each posting
46
54
  # @param debit [GlAccount]
47
55
  # @param credit [GlAccount]
48
56
  def add_posting( amount: nil, debit: nil, credit: nil )
49
- Skr::Core.logger.debug "GlTransaction add_posting #{debit} : #{credit}"
57
+ Lanes.logger.debug "GlTransaction add_posting #{debit} : #{credit}"
50
58
  self.credits.build( location: @location, is_debit: false,
51
- account: credit, amount: amount )
59
+ account: credit, amount: amount )
52
60
  self.debits.build( location: @location, is_debit: true,
53
- account: debit, amount: amount * -1 )
61
+ account: debit, amount: amount * -1 )
54
62
  end
55
63
 
56
64
  # Passes the location onto the postings.
@@ -65,7 +73,7 @@ module Skr
65
73
  # @yield [GlPosting] each posting associated with the Transaction
66
74
  def each_posting
67
75
  self.credits.each{ |posting| yield posting }
68
- self.debits.each{ |posting| yield posting }
76
+ self.debits.each{ |posting| yield posting }
69
77
  end
70
78
 
71
79
  # @return [GlTransaction] the current transaction that's in progress
@@ -82,7 +90,7 @@ module Skr
82
90
  Thread.current[:gl_transaction] ||= []
83
91
  glt = GlTransaction.new( attributes )
84
92
  Thread.current[:gl_transaction].push( glt )
85
- Skr::Core.logger.debug "B4 GlTransaction"
93
+ Lanes.logger.debug "B4 GlTransaction"
86
94
  results = yield glt
87
95
  Thread.current[:gl_transaction].pop
88
96
  if results
@@ -90,7 +98,7 @@ module Skr
90
98
  glt.assign_attributes( results[:attributes] )
91
99
  end
92
100
  glt._save_recorded
93
- Skr::Core.logger.debug "AF GlTransaction new=#{glt.new_record?} #{glt.errors.full_messages}"
101
+ Lanes.logger.debug "AF GlTransaction new=#{glt.new_record?} #{glt.errors.full_messages}"
94
102
  end
95
103
  return glt
96
104
  end
@@ -101,16 +109,13 @@ module Skr
101
109
  # @param credit [GlAccount]
102
110
  # @param options [Hash] options to pass to the [GlTransaction] if one is created
103
111
  def self.push_or_save( owner: nil, amount: nil, debit:nil, credit:nil, options:{} )
104
- if glt = self.current # we push
112
+ if (glt = self.current) # we push
105
113
  glt.add_posting( amount: amount, debit: debit, credit: credit )
106
114
  else
107
- options.merge!({
108
- source: owner,
109
- location: options[:location] || owner.location
110
- })
115
+ options.merge!(source: owner, location: options[:location] || owner.location)
111
116
  glt = GlTransaction.new( options )
112
117
  glt.add_posting( amount: amount, debit: debit, credit: credit )
113
- glt.save
118
+ glt.save!
114
119
  end
115
120
  glt
116
121
  end
@@ -152,24 +157,5 @@ module Skr
152
157
  self.period ||= GlPeriod.current
153
158
  end
154
159
 
155
- # def ensure_postings_exist
156
- # if self.new_record? and self.postings.empty?
157
- # 2.times { self.postings.build }
158
- # end
159
- # end
160
-
161
160
  end
162
161
  end
163
-
164
- __END__
165
-
166
- # export_join_tables :details
167
- # export_scope :with_details_for, lambda { | acct |
168
- # acct = acct.gsub(/\D/,'') + '%'
169
- # cs = "case when details.debit_account_number like '#{acct}' then details.debit_amount " +
170
- # "when details.credit_account_number like '#{acct}' then details.credit_amount else 0 end"
171
- # window = "#{cs} as amount, sum(#{cs}) over (order by created_at) as balance"
172
- # joins('join gl_transaction_details as details on details.gl_transaction_id = gl_transactions.id')
173
- # .select("gl_transactions.*, details.*, #{window}")
174
- # .where("debit_account_number like :acct or credit_account_number like :acct", acct: acct)
175
- # }
@@ -86,7 +86,7 @@ module Skr
86
86
  raise "Unable to apply line, either not approved or previously applied"
87
87
  end
88
88
  set_cost_from_sku_loc
89
- Core.logger.debug( "Adjusting #{self.qty} #{combined_uom} of #{sku_code} into stock")
89
+ Lanes.logger.debug( "Adjusting #{self.qty} #{combined_uom} of #{sku_code} into stock")
90
90
  self.build_sku_tran({
91
91
  :origin=>self, :qty => self.qty, :sku_loc=>self.sku_loc,
92
92
  origin_description: "IA #{self.inventory_adjustment.visible_id}:#{self.sku.code}",
@@ -3,27 +3,31 @@ module Skr
3
3
  class InvLine < Skr::Model
4
4
 
5
5
  acts_as_uom
6
- is_immutable
6
+
7
7
  is_sku_loc_line parent: "invoice"
8
8
 
9
9
  locked_fields :qty, :sku_loc_id, :so_line
10
10
  belongs_to :invoice
11
11
 
12
12
  belongs_to :so_line, export: true
13
+ belongs_to :time_entry, export: true
13
14
  belongs_to :pt_line, :inverse_of=>:inv_line, export: true
14
15
  belongs_to :sku_loc, export: true
15
16
 
16
17
  has_one :sku, :through => :sku_loc, export: true
17
18
  has_one :location, :through => :sku_loc
18
- has_one :sku_tran, :as=>:origin
19
19
 
20
- validates :sku_loc, set: true
20
+ has_many :sku_trans, :as=>:origin, autosave: true
21
+ has_many :uom_choices, :through => :sku, :source => :uoms, export: true
21
22
 
23
+ validates :sku_loc, set: true
22
24
  validates :price, :qty, :numericality=>true
23
25
  validates :uom_code, :sku_code, :description, :uom_size, :presence=>true
26
+ validate :ensure_unlocked
24
27
 
25
28
  before_validation :set_defaults
26
- before_save :adjust_inventory
29
+ before_save :perform_adjustments
30
+ before_destroy :prevent_destroy
27
31
 
28
32
  scope :with_details, lambda { |should_use=true |
29
33
  compose_query_using_detail_view( view: 'inv_details', join_to: 'inv_line_id' ) if should_use
@@ -36,15 +40,24 @@ module Skr
36
40
  .group('s.code,s.description, s.id')
37
41
  }, export: true
38
42
 
43
+ def total
44
+ (qty||0) * (price||0)
45
+ end
46
+
47
+ def ensure_unlocked
48
+ if invoice.is_locked?
49
+ self.errors.add(:invoice_date, "invoice date falls on a locked GL Period")
50
+ end
51
+ end
39
52
 
40
- private
53
+ private
41
54
 
42
55
  def set_defaults
43
56
  # puts "set_defaults #{self}"
44
57
  line = [ self.pt_line, self.so_line ].detect{ |l| ! l.blank? }
45
58
  if line
46
59
  self.uom = line.uom if self.uom.blank?
47
- self.sku_code ||= line.sku_code
60
+ self.sku_code = line.sku_code
48
61
  self.description ||= line.description
49
62
  self.sku_loc ||= line.sku_loc
50
63
  self.qty ||= line.qty
@@ -63,28 +76,33 @@ module Skr
63
76
  true
64
77
  end
65
78
 
66
- def adjust_inventory
79
+ def perform_adjustments
67
80
  debit = self.sku.gl_asset_account
68
81
  credit = self.invoice.customer.gl_receivables_account
82
+ old_extended_price = self.price_was && self.qty_was ?
83
+ self.price_was * self.qty_was : BigDecimal.new(0)
84
+ price_change = self.extended_price - old_extended_price
85
+
69
86
  if self.sku.does_track_inventory?
70
- self.build_sku_tran({
71
- origin: self, qty: self.qty*-1, sku_loc: self.sku_loc, uom: self.uom,
72
- mac: 0, cost: self.extended_price,
87
+ changed_qty = self.qty - (qty_was || 0)
88
+ self.sku_trans.build(
89
+ origin: self, qty: changed_qty * -1, sku_loc: self.sku_loc, uom: self.uom,
90
+ mac: 0, cost: price_change,
73
91
  origin_description: "INV #{self.invoice.visible_id}:#{self.sku.code}",
74
92
  debit_gl_account: debit, credit_gl_account: credit
75
- })
93
+ )
76
94
  else
77
95
  GlTransaction.push_or_save(
78
- owner: self, amount: self.total,
96
+ owner: self, amount: price_change,
79
97
  debit: debit, credit: credit
80
98
  )
81
99
  end
82
100
  true
83
101
  end
84
102
 
85
-
86
-
103
+ def prevent_destroy
104
+ errors.add(:base, "Can not destroy #{self.class.model_name}, only create/modify is allowed" )
105
+ end
87
106
  end
88
107
 
89
-
90
108
  end # Skr module
@@ -33,35 +33,37 @@ module Skr
33
33
  has_additional_events :amount_paid_change
34
34
 
35
35
  belongs_to :sales_order, export: true
36
+ belongs_to :customer_project, export: true
36
37
  belongs_to :customer, export: true
37
38
  belongs_to :location, export: true
39
+ belongs_to :pick_ticket, inverse_of: :invoice, export: true
38
40
  belongs_to :terms, class_name: 'Skr::PaymentTerm', export: true
39
- belongs_to :pick_ticket, inverse_of: :invoice, export: true
40
41
  belongs_to :billing_address, class_name: 'Skr::Address', export: { writable: true }
41
42
  belongs_to :shipping_address, class_name: 'Skr::Address', export: { writable: true }
42
43
 
43
44
  has_many :gl_transactions, :as=>:source
44
45
 
45
- has_many :lines, -> { order(:position) }, class_name: 'Skr::InvLine', inverse_of: :invoice,
46
- extend: Concerns::INV::Lines, export: { writable: true }
46
+ has_many :lines, -> { order(:position) },
47
+ class_name: 'Skr::InvLine', inverse_of: :invoice,
48
+ extend: Concerns::INV::Lines, export: { writable: true }
47
49
 
48
50
  before_save :maybe_mark_paid
49
51
 
50
52
  before_validation :set_defaults, on: :create
51
53
 
52
54
  validates :customer, :location, set: true
53
- validate :ensure_location_matches_so
55
+ validate :ensure_unlocked, :ensure_location_matches_so
54
56
 
55
57
  scope :open_for_customer, lambda{ | customer |
56
- where([ "customer_id=? and state != 'paid'", customer.is_a?(Customer) ? customer.id : customer ])
58
+ where(state: :open, customer_id: customer.is_a?(Customer) ? customer.id : customer)
57
59
  }, export: true
58
60
 
59
61
  scope :with_details, lambda { |should_use=true |
60
- compose_query_using_detail_view( view: 'inv_details', join_to: 'invoice_id' )
62
+ compose_query_using_detail_view( view: 'skr_inv_details', join_to: 'invoice_id' )
61
63
  }, export: true
62
64
 
63
65
  enum state: {
64
- open: 0,
66
+ open: 1,
65
67
  paid: 5,
66
68
  partial: 10
67
69
  }
@@ -82,7 +84,8 @@ module Skr
82
84
 
83
85
  def initialize(attributes = {})
84
86
  super
85
- self.invoice_date = Date.today
87
+ # date must be set, otherwise things like terms that are based off of it fail
88
+ self.invoice_date ||= Date.today
86
89
  end
87
90
 
88
91
  # @return [BigDecimal] total - amount_paid
@@ -95,37 +98,44 @@ module Skr
95
98
  unpaid_amount <= 0
96
99
  end
97
100
 
101
+ # @return [DateTime] when the invoice is due
102
+ def due_date
103
+ self.terms.due_date_from(invoice_date)
104
+ end
105
+
106
+ def is_locked?
107
+ GlPeriod.is_date_locked?(self.invoice_date)
108
+ end
109
+
98
110
  private
99
111
 
100
112
  # attributes for GlTransaction
101
113
  def attributes_for_gl_transaction
102
- { location: location, source: self,
103
- description: "INV #{self.visible_id}" }
114
+ { location: location, source: self,
115
+ description: "INV #{self.visible_id}" }
104
116
  end
105
117
 
106
118
  # set the state if the amount_paid was changed
107
119
  def maybe_mark_paid
108
120
  return unless amount_paid_changed?
109
121
  if self.fully_paid? && self.may_mark_paid?
110
- self.state_event = 'mark_paid'
122
+ self.mark_paid
111
123
  elsif self.amount_paid > 0 && self.may_mark_partial?
112
- self.state_event = 'mark_partial'
124
+ self.mark_partial
113
125
  end
114
126
  end
115
127
 
116
128
  def apply_balances
117
129
  return unless amount_paid_changed?
118
130
  change = amount_paid - amount_paid_was
119
-
120
- Skr::Core.logger.debug "Applying payment #{amount_paid} changed: #{change}"
121
-
131
+ Lanes.logger.debug "Applying payment #{amount_paid} changed: #{change}"
122
132
  return if change.zero?
123
-
124
133
  GlTransaction.push_or_save(
125
134
  owner: self, amount: change,
126
- debit: customer.gl_receivables_account, credit: GlAccount.default_for(:deposit_holding)
135
+ debit: customer.gl_receivables_account,
136
+ credit: GlAccount.default_for(:deposit_holding)
127
137
  )
128
- fire_event( :amount_paid_change )
138
+ fire_pubsub_event( :amount_paid_change )
129
139
  true
130
140
  end
131
141
 
@@ -139,20 +149,37 @@ module Skr
139
149
 
140
150
  if sales_order
141
151
  self.terms ||= sales_order.terms
152
+ self.form ||= sales_order.form
142
153
  self.customer = sales_order.customer
143
154
  self.po_num = sales_order.po_num if self.po_num.blank?
144
155
  self.billing_address = sales_order.billing_address if self.billing_address.blank?
145
156
  self.shipping_address = sales_order.shipping_address if self.shipping_address.blank?
146
- self.options.merge!(sales_order.options)
157
+ if self.options && sales_order.options
158
+ self.options.merge!(sales_order.options)
159
+ else
160
+ self.options = sales_order.options
161
+ end
162
+ end
163
+
164
+ if customer_project
165
+ self.customer = customer_project.customer
166
+ self.po_num = customer_project.po_num if self.po_num.blank?
147
167
  end
148
168
 
149
169
  if customer
150
- self.billing_address = customer.billing_address if self.billing_address.blank?
170
+ self.form ||= customer.get_form('invoice')
171
+ self.billing_address = customer.billing_address if self.billing_address.blank?
151
172
  self.shipping_address = customer.shipping_address if self.shipping_address.blank?
152
173
  end
153
174
 
154
175
  end
155
176
 
177
+ def ensure_unlocked
178
+ if is_locked?
179
+ self.errors.add(:invoice_date, "falls on a locked GL Period")
180
+ end
181
+ end
182
+
156
183
  def ensure_location_matches_so
157
184
  if sales_order && location != sales_order.location
158
185
  self.errors.add(:location, "#{location.code} must match location that order was taken on (#{sales_order.location.code})")
@@ -5,6 +5,8 @@ module Skr
5
5
 
6
6
  has_code_identifier :from=>'name'
7
7
 
8
+ mount_uploader :logo, Lanes::Concerns::ImageUploader
9
+
8
10
  belongs_to :address, export: { writable: true }
9
11
 
10
12
  has_many :sku_locs
@@ -15,7 +17,11 @@ module Skr
15
17
 
16
18
  before_validation :set_defaults, :on=>:create
17
19
 
18
- # @return [Location] the location that's specified by {Skr::Core::Configuration#default_location_code}
20
+ def get_logo
21
+ self.logo.present? ? self.logo : Lanes::SystemSettings.config.logo
22
+ end
23
+
24
+ # @return [Location] the location that's specified by {Skr::Configuration#default_location_code}
19
25
  def self.default
20
26
  Location.find_by_code( Skr.config.default_location_code )
21
27
  end
@@ -0,0 +1,49 @@
1
+ module Skr
2
+
3
+ class Payment < Model
4
+ has_visible_id
5
+ has_random_hash_code
6
+ has_gl_transaction
7
+
8
+ belongs_to :category, class_name: 'Skr::PaymentCategory', export: true
9
+ belongs_to :vendor, class_name: 'Skr::Vendor', export: true
10
+ belongs_to :bank_account, class_name: 'Skr::BankAccount', export: true
11
+ belongs_to :location, class_name: 'Skr::Location', export: true
12
+
13
+ validates :name, :amount, :category, :bank_account, presence: true
14
+
15
+ has_one :gl_transaction, class_name: 'Skr::GlTransaction', as: :source
16
+
17
+ before_validation :set_defaults, on: :create
18
+
19
+ after_save :apply_transaction
20
+
21
+ def latex_template_variables
22
+ { 'position' => :absolute }
23
+ end
24
+
25
+ private
26
+
27
+ def attributes_for_gl_transaction
28
+ { location: location, source: self,
29
+ description: "Payment #{self.visible_id}" }
30
+ end
31
+
32
+ def apply_transaction
33
+ credit = vendor ? vendor.gl_payables_account : category.gl_account
34
+
35
+ GlTransaction.push_or_save(
36
+ owner: self, amount: amount,
37
+ debit: bank_account.gl_account,
38
+ credit: credit
39
+ )
40
+ end
41
+
42
+ def set_defaults
43
+ self.location ||= Location.default
44
+ self.date ||= Date.today
45
+ self.check_number ||= SequentialId.next_for("Pmnt-#{bank_account.id}")
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module Skr
2
+
3
+ class PaymentCategory < Model
4
+
5
+ has_code_identifier from: 'name'
6
+
7
+ belongs_to :gl_account, class_name: 'Skr::GlAccount', export: true
8
+
9
+ end
10
+
11
+ end
@@ -6,7 +6,7 @@ module Skr
6
6
  has_code_identifier
7
7
 
8
8
  def discount
9
- @discount_percnum ||= Core::Numbers::PercNum.new( read_attribute('discount_amount') )
9
+ @discount_percnum ||= Numbers::PercNum.new( read_attribute('discount_amount') )
10
10
  end
11
11
 
12
12
  def discount_amount=(value)
@@ -35,7 +35,7 @@ module Skr
35
35
  private
36
36
 
37
37
  def adjust_inventory
38
- Core.logger.debug( "Receiving #{self.ea_qty} into stock" )
38
+ logger.debug( "Receiving #{self.ea_qty} into stock" )
39
39
  tran = self.sku_trans.build({
40
40
  origin: self, qty: self.qty,
41
41
  sku_loc: po_line.sku_loc,
@@ -61,7 +61,7 @@ module Skr
61
61
  self.sku_loc ||= so_line.sku_loc
62
62
  self.bin ||= sku_loc.bin
63
63
  self.price ||= so_line.price
64
- self.sku_code = sku_loc.sku.code if self.sku_code.blank?
64
+ self.sku_code = sku_loc.sku.code
65
65
  self.description = so_line.description if self.description.blank?
66
66
  self.uom = so_line.uom if self.uom.blank?
67
67
  true