stockor 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -4
  3. data/Gemfile.lock +104 -87
  4. data/client/skr/api.js +3 -1
  5. data/client/skr/api/Components/AddressForm.cjsx +1 -1
  6. data/client/skr/api/Components/SingleItemCart.cjsx +1 -1
  7. data/client/skr/api/SingleItemCheckout.cjsx +3 -3
  8. data/client/skr/components/BankAccountFinder.cjsx +1 -1
  9. data/client/skr/components/CreditCardForm.cjsx +1 -1
  10. data/client/skr/components/Currency.cjsx +2 -1
  11. data/client/skr/components/CustomerFinder.cjsx +1 -1
  12. data/client/skr/components/CustomerProjectFinder.cjsx +1 -1
  13. data/client/skr/components/ExpenseCategoryFinder.cjsx +34 -0
  14. data/client/skr/components/GlAccountChooser.cjsx +2 -1
  15. data/client/skr/components/InvoiceFinder.cjsx +1 -1
  16. data/client/skr/components/LatexSnippets.cjsx +3 -0
  17. data/client/skr/components/LocationChooser.cjsx +3 -3
  18. data/client/skr/components/PaymentCategoryFinder.cjsx +1 -1
  19. data/client/skr/components/SalesOrderFinder.cjsx +1 -2
  20. data/client/skr/components/SkuFinder.cjsx +1 -1
  21. data/client/skr/components/SystemSettings.cjsx +4 -1
  22. data/client/skr/components/TermsChooser.cjsx +2 -2
  23. data/client/skr/components/ToolbarButton.cjsx +7 -3
  24. data/client/skr/components/TotalsLine.cjsx +5 -1
  25. data/client/skr/components/UserPreferences.cjsx +1 -1
  26. data/client/skr/components/VendorFinder.cjsx +1 -1
  27. data/client/skr/components/address/Address.cjsx +14 -1
  28. data/client/skr/components/styles.scss +6 -0
  29. data/client/skr/index.js +1 -0
  30. data/client/skr/lib/Remote.coffee +32 -0
  31. data/client/skr/lib/index.js +2 -0
  32. data/client/skr/lib/namespace.coffee +1 -0
  33. data/client/skr/models/CreditCardGateway.coffee +1 -1
  34. data/client/skr/models/ExpenseCategory.coffee +11 -0
  35. data/client/skr/models/ExpenseEntry.coffee +64 -0
  36. data/client/skr/models/ExpenseEntryCategory.coffee +11 -0
  37. data/client/skr/models/Invoice.coffee +4 -1
  38. data/client/skr/models/Payment.coffee +2 -2
  39. data/client/skr/models/SalesOrder.coffee +3 -2
  40. data/client/skr/models/SequentialId.coffee +1 -1
  41. data/client/skr/models/Vendor.coffee +1 -1
  42. data/client/skr/models/mixins/PrintSupport.coffee +1 -1
  43. data/client/skr/screens/bank-maint/BankMaint.cjsx +1 -1
  44. data/client/skr/screens/chart-of-accounts/ChartOfAccounts.cjsx +1 -1
  45. data/client/skr/screens/customer-maint/CustomerMaint.cjsx +1 -1
  46. data/client/skr/screens/customer-projects/CustomerProjects.cjsx +1 -1
  47. data/client/skr/screens/expense-categories/ExpenseCategories.cjsx +31 -0
  48. data/client/skr/screens/expense-categories/index.js +5 -0
  49. data/client/skr/screens/expense-categories/index.scss +9 -0
  50. data/client/skr/screens/expense-entry/ApprovalRequest.coffee +14 -0
  51. data/client/skr/screens/expense-entry/ApproveDialog.cjsx +30 -0
  52. data/client/skr/screens/expense-entry/Categories.cjsx +112 -0
  53. data/client/skr/screens/expense-entry/ExpenseEntry.cjsx +193 -0
  54. data/client/skr/screens/expense-entry/Form.cjsx +54 -0
  55. data/client/skr/screens/expense-entry/Grid.cjsx +51 -0
  56. data/client/skr/screens/expense-entry/ScreenState.coffee +1 -0
  57. data/client/skr/screens/expense-entry/index.js +1 -0
  58. data/client/skr/screens/expense-entry/index.scss +106 -0
  59. data/client/skr/screens/fresh-books-import/ApiInfo.cjsx +3 -3
  60. data/client/skr/screens/fresh-books-import/ChooseRecords.cjsx +6 -4
  61. data/client/skr/screens/fresh-books-import/FreshBooksImport.cjsx +1 -1
  62. data/client/skr/screens/fresh-books-import/ViewRecords.cjsx +2 -2
  63. data/client/skr/screens/fresh-books-import/index.scss +5 -4
  64. data/client/skr/screens/gl-accounts/GlAccounts.cjsx +1 -1
  65. data/client/skr/screens/gl-transactions/GlTransactions.cjsx +1 -1
  66. data/client/skr/screens/invoice/Invoice.cjsx +6 -2
  67. data/client/skr/screens/invoice/Payment.cjsx +1 -1
  68. data/client/skr/screens/invoice/TotalExtraInfo.cjsx +32 -0
  69. data/client/skr/screens/invoice/index.scss +4 -2
  70. data/client/skr/screens/locations/Locations.cjsx +1 -1
  71. data/client/skr/screens/payment-category/PaymentCategory.cjsx +1 -1
  72. data/client/skr/screens/payment-terms/PaymentTerms.cjsx +1 -1
  73. data/client/skr/screens/payments/Payments.cjsx +13 -6
  74. data/client/skr/screens/sale-report/SaleReport.cjsx +1 -1
  75. data/client/skr/screens/sales-order/SalesOrder.cjsx +2 -1
  76. data/client/skr/screens/sku-maint/SkuMaint.cjsx +1 -1
  77. data/client/skr/screens/sku-maint/SkuUomList.cjsx +2 -2
  78. data/client/skr/screens/time-invoicing/TimeInvoicing.cjsx +4 -4
  79. data/client/skr/screens/time-tracking/EditEntry.cjsx +2 -2
  80. data/client/skr/screens/time-tracking/Entries.coffee +6 -4
  81. data/client/skr/screens/time-tracking/Popover.cjsx +11 -6
  82. data/client/skr/screens/time-tracking/TimeTracking.cjsx +12 -5
  83. data/client/skr/screens/vendor-maint/VendorMaint.cjsx +2 -2
  84. data/config/database.yml +2 -0
  85. data/config/puma.rb +0 -4
  86. data/config/routes.rb +4 -0
  87. data/config/screens.rb +17 -0
  88. data/db/migrate/20140323001446_create_so_details_view.rb +2 -2
  89. data/db/migrate/20151121211323_create_customer_project_details_views.rb +1 -1
  90. data/db/migrate/20160216142845_create_gl_account_balances_view.rb +1 -1
  91. data/db/migrate/20160726004411_string_check_numbers.rb +5 -0
  92. data/db/migrate/20160805002717_create_expenses.rb +65 -0
  93. data/db/schema.sql +394 -229
  94. data/db/seed.rb +12 -12
  95. data/lib/skr/access_roles.rb +9 -4
  96. data/lib/skr/concerns/has_gl_transaction.rb +1 -1
  97. data/lib/skr/configuration.rb +3 -1
  98. data/lib/skr/db/migration_helpers.rb +2 -2
  99. data/lib/skr/handlers/approve_expense_entries.rb +16 -0
  100. data/lib/skr/handlers/invoice_from_time_entries.rb +1 -1
  101. data/lib/skr/handlers/sequential_ids.rb +2 -2
  102. data/lib/skr/jobs/fresh_books/import.rb +18 -17
  103. data/lib/skr/model.rb +3 -0
  104. data/lib/skr/models/bank_account.rb +9 -0
  105. data/lib/skr/models/expense_category.rb +27 -0
  106. data/lib/skr/models/expense_entry.rb +76 -0
  107. data/lib/skr/models/expense_entry_category.rb +15 -0
  108. data/lib/skr/models/gl_transaction.rb +2 -2
  109. data/lib/skr/models/inv_line.rb +3 -1
  110. data/lib/skr/models/invoice.rb +9 -5
  111. data/lib/skr/models/payment.rb +1 -1
  112. data/lib/skr/models/purchase_order.rb +4 -4
  113. data/lib/skr/models/uom.rb +2 -2
  114. data/lib/skr/models/voucher.rb +4 -4
  115. data/lib/skr/print/form.rb +17 -14
  116. data/lib/skr/version.rb +1 -1
  117. data/spec/fixtures/skr/expense_category.yml +17 -0
  118. data/spec/fixtures/skr/expense_entries.yml +20 -0
  119. data/spec/fixtures/skr/expense_entry_category.yml +19 -0
  120. data/spec/fixtures/skr/gl_account.yml +10 -0
  121. data/spec/server/handlers/invoice_from_time_entries_spec.rb +2 -2
  122. data/spec/server/handlers/sequential_ids_spec.rb +1 -1
  123. data/spec/server/models/expense_category_spec.rb +17 -0
  124. data/spec/server/models/expense_entry_spec.rb +44 -0
  125. data/spec/server/models/invoice_spec.rb +0 -1
  126. data/spec/server/models/spec_helper_spec.rb +5 -10
  127. data/spec/server/spec_helper.rb +12 -11
  128. data/spec/skr/components/SkuLinesSpec.coffee +11 -9
  129. data/spec/skr/models/CustomerSpec.coffee +1 -1
  130. data/spec/skr/models/ExpenseAccountSpec.coffee +5 -0
  131. data/spec/skr/screens/expense-categories/ExpenseCategoriesSpec.coffee +5 -0
  132. data/spec/skr/screens/expense-entry/ExpenseEntrySpec.coffee +5 -0
  133. data/spec/skr/screens/locations/LocationsSpec.coffee +4 -4
  134. data/spec/skr/screens/time-tracking/TimeTrackingSpec.coffee +4 -4
  135. data/stockor.gemspec +2 -3
  136. data/templates/print/partials/header.tex.erb +1 -1
  137. data/templates/print/partials/skus_table_invoice_footer.tex.erb +22 -19
  138. data/templates/print/partials/skus_table_invoice_info_line.tex.erb +5 -1
  139. data/templates/print/types/payment/default.tex.erb +10 -10
  140. metadata +40 -14
  141. data/client/skr/api/onReady.coffee +0 -23
  142. data/spec/skr/api/SingleItemCheckoutSpec.cjsx +0 -10
  143. data/spec/skr/screens/bank-maint/BankMaintSpec.coffee +0 -5
  144. data/spec/skr/screens/gl-accounts/GlAccountsSpec.coffee +0 -5
  145. data/spec/skr/screens/invoice/InvoiceSpec.coffee +0 -5
  146. data/spec/skr/screens/payment-category/PaymentCategorySpec.coffee +0 -5
  147. data/spec/skr/screens/payments/PaymentsSpec.coffee +0 -5
  148. data/spec/skr/screens/sale-report/SaleReportSpec.coffee +0 -5
@@ -3,7 +3,7 @@ class Skr.Screens.Payments extends Skr.Screens.Base
3
3
  syncOptions:
4
4
  include: [ 'address', 'bank_account', 'category', 'vendor' ]
5
5
 
6
- dataObjects:
6
+ modelBindings:
7
7
  payment: ->
8
8
  @loadOrCreateModel({
9
9
  syncOptions: @syncOptions
@@ -16,7 +16,8 @@ class Skr.Screens.Payments extends Skr.Screens.Base
16
16
  syncOptions: @syncOptions
17
17
  src: Skr.Models.Payment, fields: [
18
18
  {id:'id', visible: false}
19
- {id:'visible_id', label: 'Payment ID', fixedWidth: 130 },
19
+ {id:'visible_id', title: 'Payment ID', fixedWidth: 130 },
20
+ {id:'check_number', title: 'Check #', fixedWidth: 130 },
20
21
  {id:'name', flex: 1}
21
22
  {
22
23
  id:'amount', fixedWidth: 120, textAlign: 'right',
@@ -32,17 +33,23 @@ class Skr.Screens.Payments extends Skr.Screens.Base
32
33
  <LC.ScreenWrapper identifier="payments">
33
34
  <SC.ScreenControls commands={@state.commands} />
34
35
  <BS.Row>
35
- <LC.RecordFinder ref="finder" sm=3 autoFocus editOnly
36
+ <LC.RecordFinder ref="finder" sm=2 autoFocus editOnly
36
37
  commands={@state.commands} model={@category}
37
38
  label='Payment ID' name='visible_id' model={@payment} query={@query}
38
39
  />
39
40
  <SC.LocationChooser hideSingle sm=2 model={@payment} />
40
41
  <SC.BankAccountFinder selectField name='bank_account'
41
42
  model={@payment} />
42
- <SC.PaymentCategoryFinder selectField name='category' labelField='code'
43
+ <SC.PaymentCategoryFinder selectField name='category' sm=2
44
+ labelField='code' label="Cateogry" model={@payment} />
45
+ <LC.DateTime name='date' format='ddd, MMM Do YYYY' sm=3
43
46
  model={@payment} />
44
- <LC.DateTime name='date' format='ddd, MMM Do YYYY'
45
- sm=3 model={@payment} />
47
+ {<LC.DisplayValue align='right' label='Number' model={@payment}
48
+ name='check_number' sm=1
49
+ /> unless @payment.isNew()}
50
+ </BS.Row>
51
+ <BS.Row>
52
+
46
53
  </BS.Row>
47
54
  <BS.Row>
48
55
  <SC.VendorFinder sm=2 selectField
@@ -36,7 +36,7 @@ class Filters extends Lanes.Models.State
36
36
 
37
37
  class Skr.Screens.SaleReport extends Skr.Screens.Base
38
38
 
39
- dataObjects:
39
+ modelBindings:
40
40
  filters: -> new Filters
41
41
 
42
42
  resetQuery: ->
@@ -4,7 +4,7 @@ class Skr.Screens.SalesOrder extends Lanes.React.Screen
4
4
  include: [ 'billing_address', 'shipping_address', 'lines' ]
5
5
  with: [ 'with_details' ]
6
6
 
7
- dataObjects:
7
+ modelBindings:
8
8
  sales_order: ->
9
9
  @loadOrCreateModel({
10
10
  syncOptions: @syncOptions, klass: Skr.Models.SalesOrder
@@ -27,6 +27,7 @@ class Skr.Screens.SalesOrder extends Lanes.React.Screen
27
27
  commands={@state.commands} />
28
28
 
29
29
  <SC.CustomerFinder
30
+ fallBackValue={@sales_order.customer_code}
30
31
  syncOptions={ include: ['billing_address', 'shipping_address' ] }
31
32
  selectField sm=3 xs=4 model={@sales_order} />
32
33
 
@@ -3,7 +3,7 @@ class Skr.Screens.SkuMaint extends Skr.Screens.Base
3
3
  syncOptions:
4
4
  {include: ['default_vendor', 'uoms']}
5
5
 
6
- dataObjects:
6
+ modelBindings:
7
7
  sku: ->
8
8
  @loadOrCreateModel({
9
9
  syncOptions: @syncOptions, klass: Skr.Models.Sku, prop: 'sku', attribute: 'code'
@@ -35,7 +35,7 @@ class UomEdit extends Lanes.React.Component
35
35
  list: React.PropTypes.instanceOf(UomList).isRequired
36
36
  uom: React.PropTypes.instanceOf(Skr.Models.Uom).isRequired
37
37
 
38
- dataObjects:
38
+ modelBindings:
39
39
  list: 'props'
40
40
  uom: 'props'
41
41
 
@@ -79,7 +79,7 @@ class EditBody extends Lanes.React.Component
79
79
  selected: React.PropTypes.instanceOf(Skr.Models.Uom)
80
80
  uoms: Lanes.PropTypes.Collection.isRequired
81
81
 
82
- dataObjects:
82
+ modelBindings:
83
83
  uoms: 'props'
84
84
 
85
85
  add: ->
@@ -4,7 +4,7 @@ class Skr.Screens.TimeInvoicing extends Skr.Screens.Base
4
4
  isEditing: true
5
5
  commands: new Skr.Screens.Commands(this, modelName: 'request')
6
6
 
7
- dataObjects:
7
+ modelBindings:
8
8
  request: -> new InvoiceRequest
9
9
  query: ->
10
10
  @gridSelections = new LC.Grid.Selections(onChange: @updateTotal)
@@ -27,7 +27,7 @@ class Skr.Screens.TimeInvoicing extends Skr.Screens.Base
27
27
  ]
28
28
  })
29
29
 
30
- setDataState: (state) ->
30
+ setModelState: (state) ->
31
31
  @updateTotal()
32
32
  @setState(state)
33
33
 
@@ -37,7 +37,7 @@ class Skr.Screens.TimeInvoicing extends Skr.Screens.Base
37
37
  return unless rate # the first call is when the model isn't parsed yet
38
38
  selectedRows = 0
39
39
  @query.results.eachRow (row, xd) ->
40
- unless xd && false == xd.selected
40
+ if LC.Grid.Selections.isSelected(row, xd)
41
41
  selectedRows += 1
42
42
  total = total.add( hoursForRow(row) * rate )
43
43
  selectionState = if selectedRows is @query.results.length then 'all'
@@ -86,7 +86,7 @@ class Skr.Screens.TimeInvoicing extends Skr.Screens.Base
86
86
  rs.eachRow (row) ->
87
87
  xd = rs.xtraData(row)
88
88
  xd.selected = false == xd.selected
89
- @query.changeCount++
89
+ @query.markModified()
90
90
  renderToggleAllButton: ->
91
91
  return null if 0 is @query.results.length
92
92
 
@@ -1,9 +1,9 @@
1
1
  class Skr.Screens.TimeTracking.EditEntry extends Lanes.React.Component
2
2
 
3
- dataObjects:
3
+ modelBindings:
4
4
  entry: -> @props.event?.get('entry')
5
5
 
6
- setDataState: (change) ->
6
+ setModelState: (change) ->
7
7
  if change.event
8
8
  @entry.fromCalEvent(change.event)
9
9
  change.event.set({content: @entry.content}, {silent: true})
@@ -11,8 +11,7 @@ class TimeEntries extends Skr.Models.TimeEntry.Collection
11
11
  query.start_at = { op: 'lt', value: range.end.toISOString() }
12
12
  @fetch({query, reset: true})
13
13
 
14
- resetEntries: (projectId, range) ->
15
- @projectId = projectId
14
+ resetEntries: (@projectId, range) ->
16
15
  query = if @projectId and @projectId isnt -1
17
16
  {customer_project_id: @projectId}
18
17
  else {}
@@ -71,6 +70,9 @@ class Skr.Screens.TimeTracking.Entries extends Lanes.Models.Base
71
70
  for event in @calEvents().events
72
71
  event.setEditing(event is editingEvent)
73
72
 
73
+ removeEntry: (entry) ->
74
+ @entries.remove(entry)
75
+
74
76
  stopEditing: ->
75
77
  for event in @calEvents().events when event.isEditing()
76
78
  entry = event.get('entry')
@@ -85,7 +87,7 @@ class Skr.Screens.TimeTracking.Entries extends Lanes.Models.Base
85
87
  date.minute(rounded).second(0)
86
88
  entry = @entries.add({
87
89
  start_at: date.subtract(1, 'hour'), end_at: date.clone().add(2, 'hour')
88
- customer_project: @project unless @project.id is -1
90
+ customer_project: @project unless @project?.id is -1
89
91
  })
90
92
  @calEvents().add( entry.toCalEvent() )
91
93
 
@@ -105,7 +107,7 @@ class Skr.Screens.TimeTracking.Entries extends Lanes.Models.Base
105
107
  @entries.resetEntries(@customer_project_id, @range)
106
108
 
107
109
  calEvents: ->
108
- @_cachedEvents ||= new LC.Calendar.Events( @entries.invoke('toCalEvent') )
110
+ @_cachedEvents ||= new LC.Calendar.Events( @entries.invokeMap('toCalEvent') )
109
111
 
110
112
  back: ->
111
113
  @set(editing: false, date: @date.clone().subtract(1, @display) )
@@ -1,6 +1,7 @@
1
1
  ##= require ./PopoverMiniControls
2
2
  ##= require ./EditEntry
3
3
 
4
+ MARGIN = 10
4
5
  class Skr.Screens.TimeTracking.Popover extends Lanes.React.Component
5
6
 
6
7
  componentWillReceiveProps: (nextProps) ->
@@ -10,8 +11,11 @@ class Skr.Screens.TimeTracking.Popover extends Lanes.React.Component
10
11
  @setState(isCanceled: false)
11
12
 
12
13
  onCancel: ->
13
- if @state.editing?.get('entry').isNew()
14
+ entry = @state.editing.get('entry')
15
+ if entry.isNew()
14
16
  @state.editing.remove()
17
+ @props.entries.removeEntry(entry)
18
+
15
19
  @props.entries.stopEditing()
16
20
  @setState(isCanceled: true, editing: null)
17
21
 
@@ -51,19 +55,20 @@ class Skr.Screens.TimeTracking.Popover extends Lanes.React.Component
51
55
  else
52
56
  [175, 60]
53
57
 
54
- # expand to show edit button
55
58
  width += 60 if @props.event and not @state.editing
56
-
57
- placement = if x > (this.props.bounds.width / 2) then 'left' else 'right'
58
-
59
+ placement = if x > (@props.bounds.width / 2) then 'left' else 'right'
59
60
  x -= width if placement is 'left'
61
+ top = Math.max( MARGIN, y - (height / 2) )
62
+ if top + height > @props.bounds.height
63
+ top = @props.bounds.height - height - MARGIN
60
64
 
61
65
  <BS.Popover className={classes}
62
66
  style={{width, height}}
63
67
  id='edit-controls'
68
+ arrowOffsetTop={y - top}
64
69
  placement={placement}
65
70
  positionLeft={x}
66
- positionTop={y - (height / 2)}
71
+ positionTop={top}
67
72
  >
68
73
  <@MiniControls />
69
74
  <@EditEntry />
@@ -6,7 +6,7 @@
6
6
 
7
7
  class Skr.Screens.TimeTracking extends Skr.Screens.Base
8
8
 
9
- dataObjects:
9
+ modelBindings:
10
10
  entries: ->
11
11
  new Skr.Screens.TimeTracking.Entries
12
12
 
@@ -14,10 +14,9 @@ class Skr.Screens.TimeTracking extends Skr.Screens.Base
14
14
  @showPopup(ev, date)
15
15
 
16
16
  showPopup: (ev, date, eventEditing = false) ->
17
- rect = _.dom(this).el.getBoundingClientRect()
17
+ rect = _.dom(this).bounds
18
18
  @entries.editing = {
19
- event: eventEditing,
20
- date: date, bounds: rect,
19
+ date: date, event: eventEditing, bounds: rect
21
20
  position: {x: ev.clientX - rect.left, y: ev.clientY - rect.top}
22
21
  }
23
22
 
@@ -42,9 +41,17 @@ class Skr.Screens.TimeTracking extends Skr.Screens.Base
42
41
  return null unless @entries.isMonth
43
42
  <div className="monthly-totals">{@entries.totalHours().toFixed(2)}</div>
44
43
 
44
+ getHeight: ->
45
+ _.dom(@).getBoundingClientRect().height
46
+
45
47
  render: ->
48
+
46
49
  <LC.ScreenWrapper identifier="time-tracking" flexVertical>
47
- <Skr.Screens.TimeTracking.Popover entries={@entries} {...@entries.editing} />
50
+ <Skr.Screens.TimeTracking.Popover
51
+ getHeight={@getHeight}
52
+ entries={@entries}
53
+ {...@entries.editing}
54
+ />
48
55
  <LC.NetworkActivityOverlay visible={@entries.isLoading} model={@entries}/>
49
56
  <Skr.Screens.TimeTracking.Header entries={@entries} />
50
57
  <BS.Row className="calendar-panel">
@@ -3,7 +3,7 @@ class Skr.Screens.VendorMaint extends Lanes.React.Screen
3
3
  syncOptions:
4
4
  include: ['billing_address', 'shipping_address']
5
5
 
6
- dataObjects:
6
+ modelBindings:
7
7
  vendor: ->
8
8
  @loadOrCreateModel({
9
9
  syncOptions: @syncOptions, klass: Skr.Models.Vendor,
@@ -31,9 +31,9 @@ class Skr.Screens.VendorMaint extends Lanes.React.Screen
31
31
  <BS.Row>
32
32
  <SC.GlAccountChooser sm=4 label="Payables Account"
33
33
  name="gl_payables_account" model={@vendor} />
34
+ <SC.TermsChooser sm=4 model={@vendor} />
34
35
  <SC.GlAccountChooser sm=4 label="Freight Account"
35
36
  name="gl_freight_account" model={@vendor} />
36
- <SC.TermsChooser sm=4 model={@vendor} />
37
37
  </BS.Row>
38
38
  <BS.Row>
39
39
  <LC.FieldSet sm=12 title="Address">
@@ -2,8 +2,10 @@ development:
2
2
  adapter: postgresql
3
3
  database: skr_dev
4
4
  host: /tmp
5
+ pool: 12
5
6
 
6
7
  test:
7
8
  adapter: postgresql
8
9
  database: skr_test
9
10
  host: /tmp
11
+ pool: 12
@@ -1,4 +0,0 @@
1
- require 'message_bus'
2
- on_worker_boot do
3
- MessageBus.after_fork
4
- end
@@ -37,9 +37,13 @@ Lanes::API.routes.for_extension 'skr' do
37
37
  resources Skr::VoLine
38
38
  resources Skr::SalesOrder
39
39
  resources Skr::SoLine
40
+ resources Skr::ExpenseCategory
41
+ resources Skr::ExpenseEntry
40
42
  resources Skr::SequentialId, controller: Skr::Handlers::SequentialIds
41
43
  resources Skr::Invoice, controller: Skr::Handlers::InvoiceFromTimeEntries,
42
44
  path: 'invoices/from-time-entries'
45
+ resources Skr::ExpenseEntry, controller: Skr::Handlers::ApproveExpenseEntries,
46
+ path: 'expense-entries/approve'
43
47
  resources Skr::Sku, path: 'public/skus', controller: Skr::Handlers::Skus, cors: '*', public: true
44
48
  resources Skr::Invoice, path: 'public/sales', controller: Skr::Handlers::Sales, cors: '*', public: true
45
49
  get 'credit-card-gateways.json', &Skr::Handlers::CreditCardGateway.get
@@ -79,6 +79,14 @@ Lanes::Screen.for_extension 'skr' do | screens |
79
79
  screen.model_class = "PaymentTerm"
80
80
  screen.view_class = "PaymentTerms"
81
81
  end
82
+ screens.define "expense-categories" do | screen |
83
+ screen.title = "Expense Categories"
84
+ screen.description = ""
85
+ screen.icon = "folder-open"
86
+ screen.group_id = "accounting"
87
+ screen.model_class = "ExpenseCategory"
88
+ screen.view_class = "ExpenseCategories"
89
+ end
82
90
  screens.define "payment-category" do | screen |
83
91
  screen.title = "Payment Categories"
84
92
  screen.description = ""
@@ -187,4 +195,13 @@ Lanes::Screen.for_extension 'skr' do | screens |
187
195
  screen.model_class = "TimeEntry"
188
196
  screen.view_class = "TimeTracking"
189
197
  end
198
+ screens.define "expense-entry" do | screen |
199
+ screen.title = "Expense Entry"
200
+ screen.description = ""
201
+ screen.icon = "shopping-bag"
202
+ screen.group_id = "customer"
203
+ screen.model_class = "ExpenseEntry"
204
+ screen.view_class = "ExpenseEntry"
205
+ end
206
+
190
207
  end
@@ -2,7 +2,7 @@ require 'skr/db/migration_helpers'
2
2
 
3
3
  class CreateSoDetailsView < ActiveRecord::Migration
4
4
  def up
5
- fk = "#{skr_prefix}sales_order_id"
5
+ fk = "sales_order_id"
6
6
  execute <<-EOS.squish
7
7
  create view #{skr_prefix}so_details as
8
8
  select so.id as #{fk},
@@ -76,7 +76,7 @@ class CreateSoDetailsView < ActiveRecord::Migration
76
76
  end
77
77
 
78
78
  def down
79
- execute "drop view #{skr_prefix}so_amount_details"
79
+ execute "drop view #{skr_prefix}so_details"
80
80
  execute "drop view #{skr_prefix}so_allocation_details"
81
81
  execute "drop view #{skr_prefix}so_dailly_sales_history"
82
82
  end
@@ -6,7 +6,7 @@ class CreateCustomerProjectDetailsViews < ActiveRecord::Migration
6
6
  execute <<-EOS
7
7
  create view #{view} as
8
8
  select
9
- cp.id as skr_customer_project_id,
9
+ cp.id as customer_project_id,
10
10
  c.code as customer_code,
11
11
  c.name as customer_description,
12
12
  s.code as sku_code,
@@ -4,7 +4,7 @@ class CreateGlAccountBalancesView < ActiveRecord::Migration
4
4
  def up
5
5
  execute <<-EOS.squish
6
6
  create view #{skr_prefix}gl_account_balances as select
7
- gla.id as skr_gl_account_id,
7
+ gla.id as gl_account_id,
8
8
  right(glp.account_number,2) as branch_number,
9
9
  coalesce(sum(glp.amount), 0.00) as balance
10
10
  from skr_gl_accounts gla
@@ -0,0 +1,5 @@
1
+ class StringCheckNumbers < ActiveRecord::Migration
2
+ def change
3
+ change_column :skr_payments, :check_number, :varchar
4
+ end
5
+ end
@@ -0,0 +1,65 @@
1
+ require 'skr/db/migration_helpers'
2
+
3
+ class CreateExpenses < ActiveRecord::Migration
4
+ def up
5
+
6
+ create_skr_table :expense_categories do |t|
7
+ t.skr_code_identifier
8
+ t.string :name, null: false
9
+ t.boolean :is_active, null: false, default: true
10
+ t.skr_reference :gl_account, null: false, single: true
11
+ t.skr_track_modifications
12
+ end
13
+
14
+ create_skr_table(:expense_entries) do |t|
15
+ t.column :uuid, 'uuid', null: false
16
+ t.text :name, null: false
17
+ t.text :memo
18
+ t.timestamp :occured, null: false
19
+ t.jsonb :metadata, default: {}
20
+ t.skr_track_modifications create_only: true
21
+ end
22
+ skr_add_index :expense_entries, :uuid, unique: true
23
+
24
+ create_skr_table(:expense_entry_categories) do |t|
25
+ t.skr_reference :category, to_table: 'expense_categories', single: true
26
+ t.skr_reference :entry, to_table: 'expense_entries', single: true
27
+ t.skr_currency :amount, null: false
28
+ end
29
+ skr_add_index :expense_entry_categories, :entry_id, unique: false
30
+
31
+ execute <<-EOS
32
+ create or replace view skr_expense_entry_details as
33
+ select
34
+ xref.expense_entry_id,
35
+ array_agg(xref.gl_transaction_id) filter (where xref.gl_transaction_id is not NULL) as gl_transaction_ids,
36
+ array_agg(xref.category_id) as category_ids,
37
+ sum(amount) as category_total,
38
+ json_agg(row_to_json(
39
+ (select t from (select category_id, amount, balance) as t(category_id, amount, balance))
40
+ )
41
+ ) category_list
42
+ from (
43
+ select
44
+ entry.id as expense_entry_id,
45
+ gl.id as gl_transaction_id,
46
+ category_id, ec.amount,
47
+ sum(amount) over (partition by category_id order by occured) as balance
48
+ from
49
+ skr_expense_entries entry
50
+ left join skr_gl_transactions gl on
51
+ gl.source_type='Skr::ExpenseEntry' and gl.source_id = entry.id
52
+ join
53
+ skr_expense_entry_categories ec on entry.id = ec.entry_id
54
+ ) as xref
55
+ group by expense_entry_id
56
+ EOS
57
+ end
58
+
59
+ def down
60
+ execute "drop view skr_expense_entry_details"
61
+ drop_skr_table :expense_entry_categories
62
+ drop_skr_table :expense_categories
63
+ drop_skr_table :expense_entries
64
+ end
65
+ end