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
@@ -0,0 +1,68 @@
1
+ class Skr.Screens.SalesOrder extends Lanes.React.Screen
2
+
3
+ syncOptions:
4
+ include: [ 'billing_address', 'shipping_address', 'lines' ]
5
+ with: [ 'with_details' ]
6
+
7
+ dataObjects:
8
+ sales_order: ->
9
+ @loadOrCreateModel({
10
+ syncOptions: @syncOptions, klass: Skr.Models.SalesOrder
11
+ prop: 'sales_order', attribute: 'visible_id'
12
+ })
13
+
14
+ getInitialState: ->
15
+ commands: new Skr.Screens.Commands(this, modelName: 'sales_order', print: true)
16
+
17
+ shouldSaveLinesImmediately: ->
18
+ not @sales_order.isNew()
19
+
20
+ render: ->
21
+ <LC.ScreenWrapper identifier="sales-order" flexVertical>
22
+ <SC.ScreenControls commands={@state.commands} />
23
+ <BS.Row>
24
+
25
+ <SC.SalesOrderFinder ref='finder' sm=2 xs=3 editOnly
26
+ syncOptions={@syncOptions} model={@sales_order}
27
+ commands={@state.commands} />
28
+
29
+ <SC.CustomerFinder selectField sm=3 xs=4
30
+ customer={@sales_order.customer} model={@sales_order} />
31
+
32
+ <LC.Input sm=3 xs=4 name='po_num' model={@sales_order} />
33
+
34
+ <SC.TermsChooser model={@sales_order} sm=3 xs=6 />
35
+
36
+ <SC.LocationChooser label='Src Location' sm=3 xs=6
37
+ model={@sales_order} />
38
+
39
+ <LC.DateTime name='order_date' format='ddd, MMM Do YYYY' sm=3 xs=6
40
+ model={@sales_order} />
41
+
42
+ <SC.PrintFormChooser label="Print Form" sm=3 model={@sales_order} sm=3 xs=6 />
43
+ </BS.Row>
44
+
45
+ <BS.Row>
46
+ <LC.Input sm=12
47
+ type='textarea'
48
+ name="notes"
49
+ model={@sales_order} />
50
+ </BS.Row>
51
+
52
+ <BS.Row>
53
+ <LC.FieldSet sm=12 title="Address" expanded={@sales_order.isNew()}>
54
+ <SC.Address lg=6 title="Billing"
55
+ model={@sales_order.billing_address} />
56
+ <SC.Address lg=6 title="Shipping"
57
+ model={@sales_order.shipping_address} />
58
+ </LC.FieldSet>
59
+ </BS.Row>
60
+
61
+ <SC.SkuLines
62
+ location={@sales_order.location}
63
+ commands={@state.commands}
64
+ saveImmediately={@shouldSaveLinesImmediately}
65
+ lines={@sales_order.lines} />
66
+
67
+ <SC.TotalsLine model={@sales_order} />
68
+ </LC.ScreenWrapper>
@@ -1,5 +1 @@
1
- // require_tree .
2
-
3
- /*
4
- Add additional requirement statements for other files that the screen uses
5
- */
1
+ //=require ./SalesOrder
@@ -0,0 +1,53 @@
1
+ class Skr.Screens.SkuMaint extends Skr.Screens.Base
2
+
3
+ syncOptions:
4
+ {include: ['default_vendor', 'uoms']}
5
+
6
+ dataObjects:
7
+ sku: ->
8
+ @loadOrCreateModel({
9
+ syncOptions: @syncOptions, klass: Skr.Models.Sku, prop: 'sku', attribute: 'code'
10
+ })
11
+
12
+ getInitialState: ->
13
+ commands: new Skr.Screens.Commands(this, modelName: 'sku')
14
+
15
+ modelForAccess: 'sku'
16
+
17
+ render: ->
18
+ <LC.ScreenWrapper identifier="sku-maint">
19
+ <SC.ScreenControls commands={@state.commands} />
20
+ <BS.Row>
21
+ <SC.SkuFinder model={@sku} sm=4 label='Code' editOnly autoFocus
22
+ syncOptions={@syncOptions}
23
+ model={@sku} name='code'
24
+ commands={@state.commands} />
25
+
26
+ <LC.Input sm=8 name="description" model={@sku} />
27
+ </BS.Row>
28
+ <BS.Row>
29
+ <SC.VendorFinder model={@sku} name="default_vendor" selectField />
30
+
31
+ <SC.GlAccountChooser sm=3 label="Asset Account"
32
+ name="gl_asset_account" model={@sku} />
33
+
34
+ <Skr.Screens.SkuMaint.SkuUomList label={"UOMs"} model={@sku} name='uoms' sm=4 />
35
+ </BS.Row>
36
+ <BS.Row>
37
+ <LC.ToggleField sm=2
38
+ label="Other Charge?"
39
+ name="is_other_charge"
40
+ model={@sku} />
41
+
42
+ <LC.ToggleField sm=2
43
+ label="Track Inventory?"
44
+ name="does_track_inventory"
45
+ model={@sku} />
46
+
47
+ <LC.ToggleField sm=2
48
+ label="Can Backorder?"
49
+ name="can_backorder"
50
+ model={@sku} />
51
+ </BS.Row>
52
+
53
+ </LC.ScreenWrapper>
@@ -0,0 +1,209 @@
1
+ class UomList extends Lanes.Models.State
2
+
3
+ session:
4
+ default: 'state'
5
+ expanded: 'state'
6
+
7
+ constructor: (@sku, expanded) ->
8
+ super()
9
+ @uoms = @sku.uoms.clone()
10
+ @default = @uoms.findWhere(code: @sku.default_uom_code)
11
+ @expanded = expanded or @uoms.first()
12
+
13
+ save: ->
14
+ @sku.associations.replace(@sku, 'uoms', uoms)
15
+ @sku.default_uom_code = @default.code
16
+
17
+ add: ->
18
+ @uoms.add({})
19
+ @default = @uoms.first() if @uoms.length is 1
20
+ @trigger('change', @uoms)
21
+
22
+ map: (fn) -> @uoms.map(fn)
23
+
24
+ isDefault: (uom) ->
25
+ uom is @default
26
+
27
+ setDefault: (uom) ->
28
+ @trigger('change')
29
+ @default = uom
30
+
31
+
32
+ class UomEdit extends Lanes.React.Component
33
+
34
+ propTypes:
35
+ list: React.PropTypes.instanceOf(UomList).isRequired
36
+ uom: React.PropTypes.instanceOf(Skr.Models.Uom).isRequired
37
+
38
+ dataObjects:
39
+ list: 'props'
40
+ uom: 'props'
41
+
42
+ onHeaderClick: (ev) ->
43
+ return if ev.target.tagName is 'I'
44
+ @list.expanded = @uom
45
+
46
+ onCheckboxChange: (ev) ->
47
+ return unless ev.target.tagName is 'I'
48
+ @props.list.setDefault( @props.uom )
49
+
50
+ render: ->
51
+ header =
52
+ <div className="cursor-pointer" onClick={@onHeaderClick}>
53
+ <LC.Icon type="" />{@props.uom.combined}
54
+ <span className='pull-right'>
55
+ <Skr.Components.Currency amount={@props.uom.price} />
56
+ <LC.Icon
57
+ style={marginLeft: '0.5em'}
58
+ onClick={@onCheckboxChange}
59
+ type={if @props.list.isDefault(@props.uom) then 'check-square-o' else 'square-o'} />
60
+ </span>
61
+ </div>
62
+
63
+ <BS.Panel ref="panel" className='form-horizontal' collapsible
64
+ expanded={@list.expanded is @uom} header={header}>
65
+
66
+ <LC.Input type="text" label='Price' name='price' labelClassName="col-xs-3"
67
+ model={@props.uom} wrapperClassName="col-xs-6" />
68
+
69
+ <LC.Input type="number" label='Size' name='size' labelClassName="col-xs-3"
70
+ model={@props.uom} wrapperClassName="col-xs-6" />
71
+
72
+ <LC.Input type="text" label='Code' name='code' labelClassName="col-xs-3"
73
+ model={@props.uom} wrapperClassName="col-xs-6"/>
74
+
75
+ </BS.Panel>
76
+
77
+
78
+ class EditBody extends Lanes.React.Component
79
+
80
+ propTypes:
81
+ selected: React.PropTypes.instanceOf(Skr.Models.Uom)
82
+ uoms: Lanes.PropTypes.Collection.isRequired
83
+
84
+ dataObjects:
85
+ uoms: 'props'
86
+
87
+ add: ->
88
+ @props.uoms.add()
89
+
90
+ render: ->
91
+ <BS.Accordion>
92
+ <div className="sku-uom-edit">
93
+ {@props.uoms.map (uom) =>
94
+ <UomEdit key={uom.cid} list={@props.uoms} uom={uom} />}
95
+ </div>
96
+ </BS.Accordion>
97
+
98
+ class UOMToken extends Lanes.React.BaseComponent
99
+
100
+ propTypes:
101
+ uom: React.PropTypes.instanceOf(Skr.Models.Uom)
102
+
103
+ onClick: (ev) ->
104
+ ev.preventDefault()
105
+ @props.onEdit(@props.uom)
106
+
107
+ render: ->
108
+ <li onClick={@onClick} className="cursor-pointer">
109
+ {@props.uom.combined}
110
+ <Skr.Components.Currency
111
+ style={marginLeft: '0.5rem'}
112
+ amount={@props.uom.price} />
113
+ </li>
114
+
115
+ class Skr.Screens.SkuMaint.SkuUomList extends Lanes.React.Component
116
+
117
+ mixins: [
118
+ LC.Form.FieldMixin
119
+ ]
120
+
121
+ getInitialState: ->
122
+ editing: false
123
+
124
+ renderDisplayValue: ->
125
+ value = @model.uoms.map (uom) ->
126
+ uom.combined
127
+ <span>{value.join(', ')}</span>
128
+
129
+ onEdit: (selected = @model.uoms.first()) ->
130
+ @setState
131
+ editing: new UomList(@model)
132
+ selected: selected
133
+
134
+ onAdd: ->
135
+ @refs.body.add()
136
+
137
+ onOk: ->
138
+ @state.editing.save()
139
+ @setState(editing: false)
140
+
141
+ onCancel: ->
142
+ @setState(editing: false)
143
+
144
+ renderEditingPopup: ->
145
+ return <span /> unless @state.editing
146
+ header =
147
+ <div>
148
+ <span>UOMs</span>
149
+ <LC.Icon type="plus" className="pull-right" onClick={@onAdd} />
150
+ </div>
151
+
152
+ <BS.Popover
153
+ ref="popover"
154
+ id='sku-edit-uoms'
155
+ title={header} placement='left'>
156
+
157
+ <div className={'clearfix'}>
158
+ <EditBody ref='body' uoms={@state.editing} selected={@state.selected} />
159
+ <div className='pull-right'>
160
+ <BS.Button onClick={@onCancel}>
161
+ Cancel
162
+ </BS.Button>
163
+ <BS.Button style={marginLeft: 10} bsStyle='primary' onClick={@onOk}>
164
+ OK
165
+ </BS.Button>
166
+ </div>
167
+ </div>
168
+ </BS.Popover>
169
+
170
+ renderEdit: (label) ->
171
+ colProps = _.omit(@props, 'name', 'label')
172
+ classNames = _.classnames(@formGroupClassNames(), 'sku-uom-list')
173
+
174
+ <BS.Col {...colProps}>
175
+ <div className={classNames}>
176
+ <label className='control-label'>
177
+ <div className="title">{label}</div>
178
+ </label>
179
+ <div className="input-group">
180
+ <div className="read-only form-control value" name={@props.name}>
181
+ <ul>
182
+ {@model.uoms.map (uom) =>
183
+ <UOMToken key={uom.cid} uom=uom onEdit={@onEdit} />}
184
+ </ul>
185
+ </div>
186
+ <span className="input-group-btn">
187
+ <BS.OverlayTrigger
188
+ trigger="click"
189
+ ref="overlay"
190
+ rootClose
191
+ arrowOffsetTop={'130px'}
192
+ container={@}
193
+ show={@state.editing}
194
+ onExit={@onCancel}
195
+ placement="left"
196
+ overlay={@renderEditingPopup()}>
197
+
198
+ <BS.Button ref="addButton" onClick={ =>
199
+ @onEdit(@model.uoms.first())}
200
+ >
201
+ <LC.Icon type="gear" />
202
+ </BS.Button>
203
+ </BS.OverlayTrigger>
204
+
205
+ </span>
206
+ </div>
207
+
208
+ </div>
209
+ </BS.Col>
@@ -1,5 +1,2 @@
1
- // require_tree .
2
-
3
- /*
4
- Add additional requirement statements for other files that the screen uses
5
- */
1
+ //=require ./SkuMaint
2
+ //=require ./SkuUomList
@@ -1,8 +1,39 @@
1
- /*
2
- If your screen does not use any custom styles
1
+ .sku-maint {
3
2
 
4
- You should remove this file and it's reference from config/screens.rb
3
+ .sku-uom-list {
4
+ .value.read-only {padding-top: 2px; }
5
+ ul {
6
+ margin: 0;
7
+ padding-left: 0;
8
+ list-style: none;
9
+ padding-right: 0;
5
10
 
6
- Otherwise Lanes will continue to fetch an empty file whenever
7
- the screen is displayed
8
- */
11
+ > li {
12
+ float: left;
13
+ display: inline-block;
14
+ padding-left: 5px;
15
+ padding-right: 5px;
16
+ margin: 1px;
17
+ padding: 0.214em 0.15em 0.214em 0.4em;
18
+ line-height: 1.4em;
19
+ text-align: center;
20
+ vertical-align: middle;
21
+ white-space: nowrap;
22
+ border-radius: 3px;
23
+ border: 1px solid #cccccc;
24
+ background-color: #cccccc;
25
+ cursor: pointer;
26
+ }
27
+ > li.rw-state-focus {
28
+ background-color: #ffffff;
29
+ border: #66afe9 1px solid;
30
+ color: #333333;
31
+ }
32
+ }
33
+ }
34
+
35
+ .sku-uom-edit {
36
+ width: 280px;
37
+ }
38
+
39
+ }
@@ -0,0 +1,156 @@
1
+ class Skr.Screens.TimeInvoicing extends Skr.Screens.Base
2
+
3
+ getInitialState: ->
4
+ isEditing: true
5
+ commands: new Skr.Screens.Commands(this, modelName: 'request')
6
+
7
+ dataObjects:
8
+ request: -> new InvoiceRequest
9
+ query: ->
10
+ @gridSelections = new LC.Grid.Selections(onChange: @updateTotal)
11
+ new Lanes.Models.Query({
12
+ defaultSort: 'start_at',
13
+ src: Skr.Models.TimeEntry, fields: [
14
+ { id:'id', visible: false }
15
+ @gridSelections
16
+ {
17
+ id: 'start_at', fixedWidth: 200,
18
+ format: Lanes.u.format.shartDateTime
19
+ }, {
20
+ id: 'end_at', fixedWidth: 200,
21
+ format: Lanes.u.format.shartDateTime
22
+ }, {
23
+ id: 'hours', fixedWidth: 80, textAlign: 'center', editable: false,
24
+ query: false, format: (v, row) -> hoursForRow(row)
25
+ }
26
+ { id: 'description', flex: 1}
27
+ ]
28
+ })
29
+
30
+ setDataState: (state) ->
31
+ @updateTotal()
32
+ @setState(state)
33
+
34
+ updateTotal: ->
35
+ total = _.bigDecimal('0')
36
+ rate = @request.customer_project.rates?.hourly
37
+ return unless rate # the first call is when the model isn't parsed yet
38
+ selectedRows = 0
39
+ @query.results.eachRow (row, xd) ->
40
+ unless xd && false == xd.selected
41
+ selectedRows += 1
42
+ total = total.add( hoursForRow(row) * rate )
43
+ selectionState = if selectedRows is @query.results.length then 'all'
44
+ else if selectedRows then 'some' else 'none'
45
+ @setState({total, selectionState})
46
+
47
+ editors: ->
48
+ selected: ({query, rowIndex}) ->
49
+ x = query.results.xtraData(rowIndex)
50
+ selected = false != x.selected
51
+ <input type="checkbox" defaultChecked={selected}
52
+ onChange={(ev) -> x.selected = ev.target.checked} />
53
+
54
+ onModelSet: (project) ->
55
+ @request.set(customer_project: project)
56
+ @query.syncOptions = {
57
+ query: { customer_project_id: project.id, is_invoiced: false }
58
+ }
59
+ @query.results.reload()
60
+
61
+ createInvoice: ->
62
+ idIndex = @query.idIndex
63
+ @request.time_entry_ids = []
64
+ @query.results.eachRow (row, xd) =>
65
+ return if xd and false == xd.selected
66
+ @request.time_entry_ids.push(row[idIndex])
67
+ @request.save(saveAll: true).then (req) =>
68
+ @query.results.reload()
69
+ @context.viewport.displayModal(@displayInvoiceResults(req))
70
+
71
+ displayInvoiceResults: (req) ->
72
+ title: "Invoice created …"
73
+ buttons: [{ title: 'OK', style: 'primary' }]
74
+ autoHide: true
75
+ body: =>
76
+ <h3>
77
+ Invoice # <SC.InvoiceLink invoice={req.invoice}
78
+ onClick={ => @context.viewport.hideModal() }
79
+ /> was successfully created.
80
+ </h3>
81
+
82
+ setNewEntriesProject: (entry) ->
83
+ entry.set({customer_project: @request.customer_project})
84
+ onSelectAll: ->
85
+ rs = @query.results
86
+ rs.eachRow (row) ->
87
+ xd = rs.xtraData(row)
88
+ xd.selected = false == xd.selected
89
+ @query.changeCount++
90
+ renderToggleAllButton: ->
91
+ return null if 0 is @query.results.length
92
+
93
+ <BS.Button className="navbar-btn toggle" onClick={@onSelectAll} bsSize='small'>
94
+ <SC.TriState type={@state.selectionState} /> Toggle
95
+ </BS.Button>
96
+
97
+ render: ->
98
+ <LC.ScreenWrapper identifier="time-invoicing" flexVertical>
99
+ <BS.Nav className="lanes-toolbar">
100
+ <div className="spacer"/>
101
+ <BS.Button navItem componentClass="button"}
102
+ onClick={@createInvoice} className="save navbar-btn">
103
+ <LC.Icon type="file-text" /> Create Invoice
104
+ </BS.Button>
105
+ </BS.Nav>
106
+ <BS.Row>
107
+ <SC.CustomerProjectFinder name='code' ref="prjfinder"
108
+ model={@request.customer_project}
109
+ onModelSet={@onModelSet}
110
+ />
111
+ </BS.Row>
112
+ <BS.Row className="flex-expand">
113
+ <LC.Grid query={@query}
114
+ toolbarChildren={@renderToggleAllButton()}
115
+ commands={@state.commands}
116
+ autoLoadQuery={false}
117
+ expandY={true}
118
+ columEditors={@editors()}
119
+ editorProps={syncImmediatly: true, beforeSave: @setNewEntriesProject, afterSave: @updateTotal}
120
+ onSelectionChange={@onSelectionChange}
121
+ height=200
122
+ allowDelete={true}
123
+ allowCreate={true}
124
+ editor={true}
125
+ />
126
+ </BS.Row>
127
+ <BS.Row>
128
+ <BS.Col xsOffset=10 xs=1>
129
+ <h4>Total:</h4>
130
+ </BS.Col>
131
+ <BS.Col xs=1>
132
+ <h4><SC.Currency amount={@state.total} /></h4>
133
+ </BS.Col>
134
+
135
+ </BS.Row>
136
+
137
+ </LC.ScreenWrapper>
138
+
139
+
140
+ hoursForRow = (row) ->
141
+ [from, to] = if _.isArray(row) then [ row[2], row[1] ] else [row.end_at, row.start_at]
142
+ hours = _.moment(from).diff(to, 'hours', true)
143
+ Math.round(hours * 100) / 100
144
+
145
+ class InvoiceRequest extends Lanes.Models.Base
146
+
147
+ props:
148
+ customer_project_id:{"type":"integer"}
149
+ time_entry_ids: { type: 'array', default: -> [] }
150
+
151
+ api_path: ->
152
+ 'skr/invoices/from-time-entries'
153
+
154
+ associations:
155
+ customer_project: { model: "CustomerProject", autoCreate: true }
156
+ invoice: { model: 'Invoice' }
@@ -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,7 @@
1
+ .time-invoicing {
2
+
3
+ .btn.toggle {
4
+ margin-left: 10px;
5
+ }
6
+
7
+ }
@@ -0,0 +1,54 @@
1
+ class Skr.Screens.TimeTracking.EditEntry extends Lanes.React.Component
2
+
3
+ dataObjects:
4
+ entry: -> @props.event?.get('entry')
5
+
6
+ setDataState: (change) ->
7
+ if change.event
8
+ @entry.fromCalEvent(change.event)
9
+ change.event.set({content: @entry.content}, {silent: true})
10
+ @forceUpdate()
11
+
12
+ getTarget: ->
13
+ return null unless @props.wrapper.isMounted()
14
+ _.dom(@props.wrapper).el
15
+
16
+ onSave: ->
17
+ event = @props.event
18
+ @entry.save().then (te) =>
19
+ event.set(_.extend({editing: false}, te.toCalEvent()))
20
+ @props.onCancel() unless te.errors
21
+
22
+ componentDidMount: ->
23
+ _.defer => _.dom(@).qs('input[name=hours]').focusAndSelect()
24
+
25
+ render: ->
26
+ props = {sm:12, editOnly: true, model: @entry}
27
+ <div className="entry-body">
28
+ <LC.NetworkActivityOverlay model={@entry} roundedCorners />
29
+ <BS.Row>
30
+ <LC.SelectField {...props} sm={8}
31
+ choices={@props.entries.available_projects.models}
32
+ name='customer_project' labelField="code" />
33
+ <LC.NumberInput {...props} sm={4} name='hours'
34
+ step={0.25} onEnter={@onSave} />
35
+ </BS.Row><BS.Row>
36
+ <LC.DateTime {...props} step={15} name="start_at"/>
37
+ </BS.Row><BS.Row>
38
+ <LC.DateTime {...props} step={15} name="end_at"/>
39
+ </BS.Row><BS.Row>
40
+ <LC.Input sm={12}
41
+ model={@entry}
42
+ ref='textarea'
43
+ onEnter={@onSave}
44
+ selectOnFocus editOnly
45
+ name="description"
46
+ type="textarea"
47
+ label='Description'
48
+ />
49
+ </BS.Row>
50
+ <BS.Row className="controls">
51
+ <BS.Button tabIndex={-1} onClick={@props.onCancel}>Cancel</BS.Button>
52
+ <BS.Button onClick={@onSave} bsStyle="primary">Save</BS.Button>
53
+ </BS.Row>
54
+ </div>