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
@@ -2,25 +2,27 @@ class Skr.Models.Vendor extends Skr.Models.Base
2
2
 
3
3
 
4
4
  props:
5
- id: {"type":"integer","required":true}
6
- billing_address_id: {"type":"integer","required":true}
7
- shipping_address_id: {"type":"integer","required":true}
8
- terms_id: {"type":"integer","required":true}
9
- gl_payables_account_id:{"type":"integer","required":true}
10
- gl_freight_account_id: {"type":"integer","required":true}
11
- code: {"type":"string","required":true}
12
- hash_code: {"type":"string","required":true}
13
- name: {"type":"string","required":true}
5
+ id: {type:"integer"}
6
+ billing_address_id: {type:"integer"}
7
+ shipping_address_id: {type:"integer"}
8
+ terms_id: {type:"integer"}
9
+ gl_payables_account_id:{type:"integer"}
10
+ gl_freight_account_id: {type:"integer"}
11
+ code: {type:"code"}
12
+ hash_code: {type:"string"}
13
+ name: {type:"string", required: true}
14
14
  notes: "string"
15
15
  account_code: "string"
16
16
  website: "string"
17
17
 
18
+ mixins: ['HasCodeField']
19
+
18
20
  associations:
19
21
  billing_address: { model: "Address" }
20
22
  shipping_address: { model: "Address" }
21
- terms: { model: "PaymentTerm" }
22
- gl_payables_account: { model: "GlAccount" }
23
- gl_freight_account: { model: "GlAccount" }
23
+ terms: { model: "PaymentTerm", required: true }
24
+ gl_payables_account: { model: "GlAccount", required: true }
25
+ gl_freight_account: { model: "GlAccount", required: true }
24
26
  purchase_orders: { collection: "PurchaseOrder" }
25
27
  vouchers: { collection: "Voucher" }
26
28
  vendor_skus: { collection: "SkuVendor" }
@@ -2,18 +2,18 @@ class Skr.Models.VoLine extends Skr.Models.Base
2
2
 
3
3
 
4
4
  props:
5
- id: {"type":"integer","required":true}
6
- voucher_id: {"type":"integer","required":true}
7
- sku_vendor_id:{"type":"integer","required":true}
5
+ id: {type:"integer"}
6
+ voucher_id: {type:"integer"}
7
+ sku_vendor_id:{type:"integer"}
8
8
  po_line_id: "integer"
9
- sku_code: {"type":"string","required":true}
10
- part_code: {"type":"string","required":true}
11
- description: {"type":"string","required":true}
12
- uom_code: {"type":"string","required":true}
13
- uom_size: {"type":"integer","required":true}
14
- position: {"type":"integer","required":true}
15
- qty: {"type":"integer","required":true,"default":"0"}
16
- price: {"type":"bigdec","required":true}
9
+ sku_code: {type:"string"}
10
+ part_code: {type:"string"}
11
+ description: {type:"string"}
12
+ uom_code: {type:"string"}
13
+ uom_size: {type:"integer"}
14
+ position: {type:"integer"}
15
+ qty: {type:"integer", "default":"0"}
16
+ price: {type:"bigdec"}
17
17
 
18
18
  associations:
19
19
  voucher: { model: "Voucher" }
@@ -2,15 +2,17 @@ class Skr.Models.Voucher extends Skr.Models.Base
2
2
 
3
3
 
4
4
  props:
5
- id: {"type":"integer","required":true}
6
- visible_id: {"type":"integer","required":true}
7
- vendor_id: {"type":"integer","required":true}
5
+ id: {type:"integer"}
6
+ visible_id: {type:"visible_id"}
7
+ vendor_id: {type:"integer"}
8
8
  purchase_order_id:"integer"
9
- terms_id: {"type":"integer","required":true}
10
- state: {"type":"string","required":true}
9
+ terms_id: {type:"integer"}
10
+ state: {type:"string"}
11
11
  refno: "string"
12
12
  confirmation_date:"any"
13
13
 
14
+ mixins: [ 'HasVisibleId' ]
15
+
14
16
  associations:
15
17
  vendor: { model: "Vendor" }
16
18
  customer: { model: "Customer" }
@@ -0,0 +1,7 @@
1
+ Skr.Models.Mixins.HasVisibleId = {
2
+
3
+ invalidChars: /[^A-Z0-9a-z]/
4
+
5
+ visibleIdentifier: -> @visible_id
6
+
7
+ }
@@ -0,0 +1,6 @@
1
+ Skr.Models.Mixins.PrintSupport = {
2
+
3
+ pdfDownloadUrl: ->
4
+ "#{Lanes.config.api_path}skr/print/#{@modelTypeIdentifier()}/#{@hash_code}.pdf"
5
+
6
+ }
@@ -0,0 +1,61 @@
1
+ ASSOCIATIONS =
2
+ uom_choices: { collection: "Uom", options: ->
3
+ with: {for_sku_loc: @sku_loc_id}, query: {}
4
+ }
5
+ sku_choices: { collection: "Sku", options: ->
6
+ with: {in_location: @location_id}, query: {}
7
+ include: ['sku_locs', 'uoms']
8
+ }
9
+ sku: { model: "Sku" }
10
+ uom: { model: "Uom" }
11
+ sku_loc: { model: "SkuLoc" }
12
+
13
+
14
+ DERIVED =
15
+ total: deps: ['qty', 'price'], fn: ->
16
+ @qty ||= 0
17
+ @price ||= 0
18
+ _.bigDecimal(@qty * @price)
19
+
20
+ Skr.Models.Mixins.SkuLine = {
21
+
22
+ included: (klass) ->
23
+ _.extend( klass::derived ||= {}, DERIVED)
24
+ _.extend( klass::associations ||= {}, ASSOCIATIONS)
25
+
26
+ initialize: ->
27
+ @uom.size = @uom_size
28
+ @uom.code = @uom_code
29
+ @on('change:sku', @onSkuChange)
30
+ @on('change:uom', @onUomChange)
31
+ @on('change:location_id', @onLocationChange)
32
+ @uom_choices.on("add", @onUomsLoad, this)
33
+
34
+ onLocationChange: ->
35
+ if @location_id
36
+ @sku_choices.options.with.in_location = @location_id
37
+
38
+ onUomsLoad: ->
39
+ uom = this.uom_choices.findWhere(size: @uom_size, code: @uom_code)
40
+ this.uom.set( uom.serialize() ) if uom
41
+
42
+ onSkuChange: ->
43
+ return unless @sku
44
+ sl = @sku.sku_locs.findWhere(sku_id: @sku.id)
45
+ if sl
46
+ @set(sku_loc: sl)
47
+ @uom_choices.options.with.for_sku_loc = sl.id
48
+ unless @sku.uoms.isEmpty()
49
+ @uom_choices.reset(@sku.uoms.models)
50
+ uom = @sku.uoms.findWhere(size: @uom_size) or @sku.uoms.first()
51
+ this.set(uom: uom)
52
+ @sku_code = @sku.code if @sku.code
53
+ @description = @sku.description if @sku.description
54
+
55
+ onUomChange: (uom) ->
56
+ return unless uom
57
+ newPrice = Skr.Models.PricingProvider.price({uom})
58
+ @price = newPrice unless newPrice.eq(0)
59
+ @uom_code = uom.code
60
+ @uom_size = uom.size
61
+ }
@@ -0,0 +1,29 @@
1
+ class Skr.Screens.Commands extends Lanes.Screens.Commands
2
+
3
+ constructor: ->
4
+ super
5
+
6
+ canPrint: ->
7
+ model = @getModel()
8
+ not model.isNew() and model?.pdfDownloadUrl
9
+
10
+ printModel: ->
11
+ model = @getModel()
12
+ width = Math.min(1000, window.screen.width - 20)
13
+ height = Math.min(800, window.screen.height - 30)
14
+ options = ["toolbar=no", "location=" + (if window.opera then "no" else "yes"),
15
+ "directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no",
16
+ "width=" + width, "height=" + height,
17
+ "top=" + (window.screen.height - height) / 2,
18
+ "left=" + (window.screen.width - width) / 2].join()
19
+
20
+ prn = window.open('', 'lanes-print', options)
21
+ printFn = ->
22
+ prn.location.href = _.result(model, 'pdfDownloadUrl')
23
+ _.delay ->
24
+ prn?.print?()
25
+ , 5000 # onload doesn't seem to work with PDF's so we just delay a bit
26
+ if model.isDirty
27
+ model.save().then printFn
28
+ else
29
+ printFn()
@@ -0,0 +1,43 @@
1
+ class Skr.Screens.BankMaint extends Skr.Screens.Base
2
+ syncOptions:
3
+ include: [ 'address' ]
4
+
5
+ dataObjects:
6
+ bank: ->
7
+ @loadOrCreateModel({
8
+ syncOptions: @syncOptions, klass: Skr.Models.BankAccount
9
+ prop: 'bank', attribute: 'code'
10
+ })
11
+
12
+ getInitialState: ->
13
+ commands: new Skr.Screens.Commands(this, modelName: 'bank', print: true)
14
+
15
+ render: ->
16
+ <LC.ScreenWrapper identifier="bank-maint">
17
+ <SC.ScreenControls commands={@state.commands} />
18
+
19
+ <BS.Row>
20
+ <SC.BankAccountFinder ref='finder' label='Code' sm=3 xs=4 editOnly
21
+ syncOptions={@syncOptions} model={@bank}
22
+ commands={@state.commands} />
23
+
24
+ <LC.Input sm=6 name="name" model={@bank} />
25
+
26
+ <SC.GlAccountChooser sm=3 label="GL Account"
27
+ name="gl_account" model={@bank} />
28
+ </BS.Row>
29
+ <BS.Row>
30
+ <LC.Input sm=12 name="description" model={@bank} />
31
+ </BS.Row>
32
+
33
+ <SC.Address lg=6 title="Address for Check Printing"
34
+ model={@bank.address} />
35
+
36
+ <LC.FieldSet sm=12 title="Account Information *">
37
+ <p>* Can be ommited if pre-printed checks are used</p>
38
+ <BS.Row>
39
+ <LC.Input sm=6 name="routing_number" model={@bank} />
40
+ <LC.Input sm=6 name="account_number" model={@bank} />
41
+ </BS.Row>
42
+ </LC.FieldSet>
43
+ </LC.ScreenWrapper>
@@ -0,0 +1,5 @@
1
+ //= require_tree .
2
+
3
+ /*
4
+ Add additional requirement statements for other files that the screen uses
5
+ */
@@ -0,0 +1,40 @@
1
+ class Skr.Screens.ChartOfAccounts extends Skr.Screens.Base
2
+
3
+ modelForAccess: 'gl-transaction'
4
+ dataObjects:
5
+ query: ->
6
+ new Lanes.Models.Query
7
+ title: 'Lines', src: Skr.Models.GlAccount
8
+ syncOptions: {with: 'with_balances'}
9
+ fields: [
10
+ { id:'id', visible: false }
11
+ { id: 'number', label: 'Acct #', fixedWidth: 120 }
12
+ 'description'
13
+ {
14
+ id: 'balance', fixedWidth: 120, textAlign: 'right'
15
+ format: Lanes.u.format.currency
16
+ }
17
+ ]
18
+
19
+ reload: ->
20
+ @query.results.reload()
21
+
22
+ onRowClick: (account) ->
23
+ Lanes.Screens.Definitions.all.get('gl-transactions')
24
+ .display(props: {account: account})
25
+
26
+ render: ->
27
+ <LC.ScreenWrapper flexVertical identifier="chart-of-accounts">
28
+ <div className="heading">
29
+ <h3>Chart of Accounts</h3>
30
+ <span className="explain">Click row to review transactions</span>
31
+ <BS.Button onClick={@reload}>Reload</BS.Button>
32
+ </div>
33
+ <LC.Grid
34
+ onSelectionChange={@onRowClick}
35
+ query={@query}
36
+ ref='grid'
37
+ expandY={true}
38
+ />
39
+
40
+ </LC.ScreenWrapper>
@@ -0,0 +1 @@
1
+ //=require ./ChartOfAccounts
@@ -0,0 +1,12 @@
1
+ .chart-of-accounts {
2
+ .heading {
3
+ display: flex;
4
+ align-items: baseline;
5
+ justify-content: space-between;
6
+ .explain {
7
+ flex: 1;
8
+ text-align: center;
9
+ }
10
+ }
11
+
12
+ }
@@ -1,58 +1,57 @@
1
- class Skr.Screens.CustomerMaint extends Lanes.React.Screen
1
+ class Skr.Screens.CustomerMaint extends Skr.Screens.Base
2
2
 
3
+ syncOptions: {include: ['billing_address', 'shipping_address']}
3
4
  dataObjects:
4
5
  customer: ->
5
- @props.customer || new Skr.Models.Customer
6
- query: ->
7
- new Lanes.Models.Query({
8
- loadAssociations: ['billing_address', 'shipping_address']
9
- modelClass: Skr.Models.Customer, fields: [
10
- {id:'id', visible: false}
11
- 'code', 'name', 'notes',
12
- { id: 'open_balance', flex: 0.5, textAlign: 'center' }
13
- ]
6
+ @loadOrCreateModel({
7
+ syncOptions: @syncOptions, klass: Skr.Models.Customer,
8
+ prop: 'customer', attribute: 'code'
14
9
  })
15
10
 
16
11
  getInitialState: ->
17
- commands: new Lanes.Screens.Commands(this, modelName: 'customer')
12
+ commands: new Skr.Screens.Commands(this, modelName: 'customer')
18
13
 
19
14
  modelForAccess: 'customer'
20
15
 
16
+ setForm: (val, {type}) ->
17
+ @customer.forms = _.extend({}, @customer.forms, {"#{type}": val})
18
+
21
19
  render: ->
22
- <div className="customer-maint">
23
- <LC.Toolbar commands={@state.commands} />
24
- <LC.ErrorDisplay model={@customer} />
20
+ <LC.ScreenWrapper identifier="customer-maint">
21
+ <SC.ScreenControls commands={@state.commands} />
25
22
  <BS.Row>
26
- <LC.RecordFinder ref="finder" sm=4 autoFocus
27
- model={@customer}
28
- commands={@state.commands}
29
- query={@query} />
30
- <LC.TextField sm=8 name="name" model={@customer} />
23
+ <SC.CustomerFinder sm=4 editOnly ref="finder"
24
+ syncOptions={@syncOptions}
25
+ commands={@state.commands} model={@customer} name='code' />
26
+ <LC.Input sm=8 name="name" model={@customer} />
31
27
  </BS.Row>
32
28
  <BS.Row>
33
- <LC.TextArea sm=12
34
- name="notes"
35
- model={@customer} />
29
+ <LC.Input sm=12
30
+ type='textarea'
31
+ name="notes"
32
+ model={@customer} />
36
33
  </BS.Row>
37
34
  <BS.Row>
38
- <LC.SelectField sm=6
39
- label="Receivables Account"
40
- name="gl_receivables_account"
41
- labelField="combined_name"
42
- model={@customer} />
43
- <LC.SelectField sm=6
44
- label="Payment Terms"
45
- name="terms"
46
- labelField="code"
47
- model={@customer} />
35
+ <SC.GlAccountChooser sm=3 model={@customer}
36
+ label="Receivables Account" name="gl_receivables_account"/>
37
+ <SC.TermsChooser model={@customer} sm=3 />
38
+ <SC.PrintFormChooser
39
+ label="Sales Order Form" sm=3 model={@customer}
40
+ onChange={@setForm} type="sales_order"
41
+ value={@customer.forms?.sales_order}
42
+ choices={Skr.Models.SalesOrder.Templates} />
43
+ <SC.PrintFormChooser
44
+ label="Invoice Form" sm=3 model={@customer}
45
+ onChange={@setForm} type="invoice"
46
+ value={@customer.forms?.invoice}
47
+ choices={Skr.Models.Invoice.Templates} />
48
48
  </BS.Row>
49
49
  <BS.Row>
50
50
  <LC.FieldSet sm=12 title="Address">
51
- <Skr.Components.Address lg=6 title="Billing"
51
+ <SC.Address lg=6 title="Billing"
52
52
  model={@customer.billing_address} />
53
- <Skr.Components.Address lg=6 title="Shipping"
53
+ <SC.Address lg=6 title="Shipping"
54
54
  model={@customer.shipping_address} />
55
55
  </LC.FieldSet>
56
56
  </BS.Row>
57
-
58
- </div>
57
+ </LC.ScreenWrapper>
@@ -0,0 +1,70 @@
1
+ class Skr.Screens.CustomerProjects extends Skr.Screens.Base
2
+
3
+ getInitialState: ->
4
+ commands: new Skr.Screens.Commands(this, modelName: 'project')
5
+
6
+ dataObjects:
7
+ project: ->
8
+ @loadOrCreateModel({
9
+ klass: Skr.Models.CustomerProject,
10
+ prop: 'project', attribute: 'code'
11
+ })
12
+
13
+ modelForAccess: 'customer-project'
14
+
15
+ getHourlyRate: -> @project.rates?.hourly
16
+ setHourlyRate: (value) ->
17
+ @project.rates = _.extend({}, @project.rates, {hourly: value.replace(/[^0-9.]/g, '')})
18
+ ColorOption: (props) ->
19
+ <div className={"color-#{props.item.id}"}>{props.item.name}</div>
20
+
21
+ setColor: (value) ->
22
+ @project.options = _.extend({}, @project.options, {color: value.id})
23
+ @forceUpdate()
24
+ getColorReadOnly: ->
25
+ index = @getColor()
26
+ color = _.findWhere(Skr.Models.CustomerProject.COLORS, id: index)
27
+ <div className={"ro color-#{index}"}>{color?.name}</div>
28
+
29
+ getColor: ->
30
+ @project.options?.color
31
+
32
+ render: ->
33
+ <LC.ScreenWrapper identifier="customer-projects">
34
+ <SC.ScreenControls commands={@state.commands} />
35
+ <BS.Row>
36
+ <SC.CustomerProjectFinder ref='finder' commands={@state.commands}
37
+ model={@project} autoFocus editOnly sm=3 />
38
+
39
+ <SC.CustomerFinder selectField sm=3
40
+ label='Customer' model={@project} name='customer' />
41
+
42
+ <SC.SkuFinder selectField sm=3 model={@project} name='sku' />
43
+ <LC.Input name="po_num" model={@project} sm=3 />
44
+ </BS.Row>
45
+ <BS.Row>
46
+ <LC.Input sm=2 name="rates" label='Hourly Rate' model={@project}
47
+ setValue={@setHourlyRate} getValue={@getHourlyRate} />
48
+
49
+ <LC.FieldWrapper sm=2
50
+ label="Entry Color"
51
+ className="color-selection"
52
+ value={@getColorReadOnly()}
53
+ >
54
+ <Lanes.Vendor.ReactWidgets.DropdownList
55
+ className='colors'
56
+ data={Skr.Models.CustomerProject.COLORS}
57
+ valueField='id' textField='name'
58
+ value={@getColor()} onChange={@setColor}
59
+ valueComponent={@ColorOption}
60
+ disabled={!@state.commands.isEditing()}
61
+ itemComponent={@ColorOption} />
62
+ </LC.FieldWrapper>
63
+
64
+ <LC.Input name="name" model={@project} sm=8 />
65
+ </BS.Row>
66
+ <BS.Row>
67
+ <LC.Input name="description" model={@project} sm=12 />
68
+ </BS.Row>
69
+
70
+ </LC.ScreenWrapper>
@@ -0,0 +1,5 @@
1
+ //= require_tree .
2
+
3
+ /*
4
+ Add additional requirement statements for other files that the screen uses
5
+ */
@@ -0,0 +1,25 @@
1
+ /*
2
+ If your screen does not use any custom styles
3
+
4
+ You should remove this file and it's reference from config/screens.rb
5
+
6
+ Otherwise Lanes will continue to fetch an empty file whenever
7
+ the screen is displayed
8
+ */
9
+ @import "lanes/screens/styles";
10
+
11
+ .customer-projects {
12
+ @include lanes-unpadded-dropdown();
13
+ @each $current-color in $lanes-color-selections {
14
+ $i: index($lanes-color-selections, $current-color);
15
+ .color-#{$i} {
16
+ background: $current-color;
17
+ color: nth($lanes-text-color-selections, $i);
18
+ }
19
+ }
20
+ .color-selection {
21
+ .ro {
22
+ padding-left: 0.5rem;
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,35 @@
1
+ class Skr.Screens.FreshBooksImport.ApiInfo extends Lanes.React.Component
2
+ listenNetworkEvents: true
3
+ dataObjects:
4
+ import: 'props'
5
+ startImport: ->
6
+ @import.save()
7
+
8
+ render: ->
9
+ return null if @import.isComplete() or @import.job.isSubmitted
10
+ <div className="api-info">
11
+ <LC.NetworkActivityOverlay model={@import} />
12
+ <BS.Row>
13
+ <BS.Col sm=12>
14
+ <h3>Freshbooks Account Information</h3>
15
+ <p>
16
+ The importer will download a summary of all Clients,
17
+ Projects, Invoices, and time entries from Fresh Books
18
+ and allow you to choose which ones to import.
19
+ </p>
20
+ <p>Your access information will not be stored and is only used to download records</p>
21
+ </BS.Col>
22
+ </BS.Row>
23
+ <BS.Row>
24
+ <LC.Input name='api_key' label='API Key' sm=7 model={@import} />
25
+ <LC.Input name='domain' label='Company' sm=3 model={@import} />
26
+ <LC.FormGroup className='domain' sm=2 label=''>.freshbooks.com</LC.FormGroup>
27
+ </BS.Row>
28
+ <BS.Row>
29
+ <BS.Col smOffset=9 sm=2>
30
+ <BS.Button bsStyle="primary" bsSize="large" onClick={@startImport}>
31
+ Start Import
32
+ </BS.Button>
33
+ </BS.Col>
34
+ </BS.Row>
35
+ </div>
@@ -0,0 +1,116 @@
1
+ USERS = new Lanes.Models.User.Collection
2
+ USERS.ensureLoaded()
3
+ IGNORED_PROPS = ['selected', 'mapped_user_id', 'customer_code']
4
+
5
+ class TextInput extends Lanes.React.Component
6
+ setCode: (ev) ->
7
+ @props.row.customer_code = ev.target.value.toUpperCase()
8
+ @forceUpdate()
9
+
10
+ render: ->
11
+ <input value={@props.row.customer_code} onChange={@setCode} />
12
+
13
+ class UserSelect extends Lanes.React.Component
14
+ dataObjects:
15
+ user: -> new Lanes.Models.User
16
+
17
+ getUser: ->
18
+ if @props.row.mapped_user_id
19
+ USERS.get(@props.row.mapped_user_id)
20
+ else null
21
+
22
+ setUser: (user) ->
23
+ @props.row.mapped_user_id = user.id
24
+ @forceUpdate()
25
+
26
+ render: ->
27
+ <LC.SelectField
28
+ editOnly unstyled
29
+ model={this.user}
30
+ name="user"
31
+ labelField='login'
32
+ queryModel={Lanes.Models.User}
33
+ getSelection={@getUser}
34
+ setSelection={@setUser}
35
+ choices={USERS.models}
36
+ />
37
+
38
+
39
+ class RecordRow extends Lanes.React.BaseComponent
40
+ isChecked: -> not @props.row.selected? or @props.row.selected
41
+ onChange: (ev) ->
42
+ @props.row.selected = ev.target.checked
43
+ @forceUpdate()
44
+ onRowClick: (ev) ->
45
+ return if ev.target.tagName is 'INPUT'
46
+ @props.row.selected = if @props.row.selected? then !@props.row.selected else false
47
+ @forceUpdate()
48
+ render: ->
49
+ <tr onClick={@onRowClick}>
50
+ <td>
51
+ <input type="checkbox" onChange={@onChange} checked={@isChecked()} />
52
+ </td>
53
+ {for key, value of _.omit(@props.row, IGNORED_PROPS)
54
+ <td key={key}>{value}</td>}
55
+ {for Field in (@props.xtra || [])
56
+ <td key={Field.label}><Field.control row={@props.row} /></td>}
57
+ </tr>
58
+
59
+ class Skr.Screens.FreshBooksImport.ChooseRecords extends Lanes.React.Component
60
+ listenNetworkEvents: true
61
+ dataObjects:
62
+ import: 'props'
63
+ job: -> @props.import.job
64
+
65
+ RecordTable: (props) ->
66
+ records = @import.recordsForType(props.type)
67
+ keys = _.without( _.keys(_.first(records)), IGNORED_PROPS)
68
+ xtraFields = []
69
+ if props.type is 'staff'
70
+ xtraFields.push { label: 'Reassign To', control: UserSelect }
71
+ if props.type is 'clients'
72
+ xtraFields.push { label: 'Customer Code', control: TextInput }
73
+
74
+ <BS.Table responsive striped bordered condensed hover
75
+ className={props.type} >
76
+ <thead>
77
+ <tr>
78
+ <th>Select</th>
79
+ {for key, i in keys
80
+ <th key={i}>{_.titleize _.humanize key}</th>}
81
+ {for field in xtraFields
82
+ <th key={field.label}>{field.label}</th>}
83
+ </tr>
84
+ </thead>
85
+ <tbody>
86
+ {for row, i in records
87
+ <RecordRow key={i} row={row} xtra={xtraFields} />}
88
+ </tbody>
89
+ </BS.Table>
90
+
91
+ startImport: -> @import.complete()
92
+
93
+ renderHeader: ->
94
+ button =
95
+ <BS.Button
96
+ bsStyle="primary" bsSize="large"
97
+ onClick={@startImport}>
98
+ Start Import
99
+ </BS.Button> unless @import.job.isExecuting
100
+
101
+ <div className="header">
102
+ <h3>Select Records for Import</h3>
103
+ {button}
104
+ </div>
105
+
106
+ render: ->
107
+ return null unless @import.hasPendingRecords()
108
+ <div className="import-records">
109
+ {@renderHeader()}
110
+ <BS.Tabs animation={false} defaultActiveKey={0}>
111
+ {for type, i in @import.recordTypes when @import.recordsForType(type)
112
+ <BS.Tab eventKey={i} key={i} title={_.titleize(type)} animation={false}>
113
+ <@RecordTable type={type} />
114
+ </BS.Tab>}
115
+ </BS.Tabs>
116
+ </div>