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
@@ -12,8 +12,9 @@ class Skr.Components.Currency extends Lanes.React.Component
12
12
  symbol: React.PropTypes.string
13
13
 
14
14
  render: ->
15
+ colProps = _.omit(@props, _.keys(@constructor.propTypes))
15
16
  className = _.classnames 'currency', @props.className
16
- <span {...@props} className={className}>
17
+ <span {...colProps} className={className}>
17
18
  <span className="sym">{@props.symbol}</span>
18
19
  {Lanes.u.format.currency(@props.amount)}
19
20
  </span>
@@ -10,7 +10,7 @@ class Skr.Components.CustomerFinder extends Lanes.React.Component
10
10
  getDefaultProps: ->
11
11
  autoFocus: false, label: 'Customer Code', name: 'customer'
12
12
 
13
- dataObjects:
13
+ modelBindings:
14
14
  query: ->
15
15
  new Lanes.Models.Query({
16
16
  syncOptions: @props.syncOptions, autoRetrieve: true
@@ -10,7 +10,7 @@ class Skr.Components.CustomerProjectFinder extends Lanes.React.Component
10
10
  getDefaultProps: ->
11
11
  autoFocus: false, label: 'Project Code', name: 'code'
12
12
 
13
- dataObjects:
13
+ modelBindings:
14
14
  query: ->
15
15
  new Lanes.Models.Query({
16
16
  autoRetrieve: true, syncOptions:
@@ -0,0 +1,34 @@
1
+ class Skr.Components.ExpenseCategoryFinder extends Lanes.React.Component
2
+
3
+ propTypes:
4
+ model: Lanes.PropTypes.Model
5
+ commands: React.PropTypes.object
6
+ autoFocus: React.PropTypes.bool
7
+ name: React.PropTypes.string
8
+ selectField: React.PropTypes.bool
9
+
10
+ getDefaultProps: ->
11
+ autoFocus: false, label: 'Expense Category', name: 'code'
12
+
13
+ modelBindings:
14
+ query: ->
15
+ new Lanes.Models.Query({
16
+ syncOptions: @props.syncOptions, autoRetrieve: true
17
+ src: Skr.Models.ExpenseCategory, fields: [
18
+ {id:'id', visible: false}
19
+ {id: 'code', fixedWidth: 130 },
20
+ {id: 'name', flex: 1}
21
+ ]
22
+ })
23
+
24
+ render: ->
25
+ props = _.clone(@props)
26
+
27
+ if props.selectField
28
+ <LC.SelectField queryModel={Skr.Models.ExpenseCategory}
29
+ labelField='code' sm=2 {...props} fetchOnSelect={false} />
30
+ else
31
+ <LC.RecordFinder ref="finder" sm=3 autoFocus
32
+ commands={@props.commands}
33
+ query={@query}
34
+ {...props} />
@@ -9,7 +9,7 @@ class Skr.Components.GlAccountChooser extends Lanes.React.Component
9
9
  getDefaultProps: ->
10
10
  label: 'Account', name: 'gl_account'
11
11
 
12
- dataObjects:
12
+ modelBindings:
13
13
  query: ->
14
14
  new Lanes.Models.Query({
15
15
  syncOptions: @props.syncOptions, autoRetrieve: true
@@ -34,5 +34,6 @@ class Skr.Components.GlAccountChooser extends Lanes.React.Component
34
34
  choices={Skr.Models.GlAccount.all.models}
35
35
  labelField="combined_name"
36
36
  model={@props.model}
37
+ filter='contains'
37
38
  {...props}
38
39
  />
@@ -7,7 +7,7 @@ class Skr.Components.InvoiceFinder extends Lanes.React.Component
7
7
  getDefaultProps: ->
8
8
  autoFocus: true, name: 'visible_id', label: 'Invoice #'
9
9
 
10
- dataObjects:
10
+ modelBindings:
11
11
  query: ->
12
12
  new Lanes.Models.Query({
13
13
  initialFieldIndex: 1
@@ -1,5 +1,8 @@
1
1
  class Skr.Components.LatexSnippets extends Lanes.React.Component
2
2
 
3
+ propTypes:
4
+ settings: React.PropTypes.object.isRequired
5
+
3
6
  getInitialState: ->
4
7
  name: ''
5
8
  latex: ''
@@ -1,14 +1,13 @@
1
1
  class Skr.Components.LocationChooser extends Lanes.React.Component
2
2
 
3
3
  propTypes:
4
- onModelSet: React.PropTypes.func
5
4
  name: React.PropTypes.string
6
5
  hideSingle: React.PropTypes.bool
7
6
 
8
7
  getDefaultProps: ->
9
8
  label: 'Location', name: 'location'
10
9
 
11
- dataObjects:
10
+ modelBindings:
12
11
  query: ->
13
12
  new Lanes.Models.Query({
14
13
  autoRetrieve: true
@@ -26,7 +25,8 @@ class Skr.Components.LocationChooser extends Lanes.React.Component
26
25
  if @props.hideSingle and Skr.Models.Location.all.length < 2
27
26
  return LC.SelectField.renderEmptyColumn(@props)
28
27
 
29
- props = _.clone(@props)
28
+ props = _.omit(@props, 'hideSingle')
29
+
30
30
  if props.displayFinder
31
31
  <LC.RecordFinder ref="finder" sm=3 autoFocus
32
32
  commands={@state.commands}
@@ -10,7 +10,7 @@ class Skr.Components.PaymentCategoryFinder extends Lanes.React.Component
10
10
  getDefaultProps: ->
11
11
  autoFocus: false, label: 'Payment Category', name: 'payment_category'
12
12
 
13
- dataObjects:
13
+ modelBindings:
14
14
  query: ->
15
15
  new Lanes.Models.Query({
16
16
  syncOptions: @props.syncOptions, autoRetrieve: true
@@ -7,10 +7,9 @@ class Skr.Components.SalesOrderFinder extends Lanes.React.Component
7
7
  autoFocus: React.PropTypes.bool
8
8
 
9
9
  getDefaultProps: ->
10
- editing: true
11
10
  autoFocus: true, name: 'visible_id', label: 'Sales Order #'
12
11
 
13
- dataObjects:
12
+ modelBindings:
14
13
  query: ->
15
14
  new Lanes.Models.Query({
16
15
  initialFieldIndex: 1, title: 'Sales Order', autoRetrieve: true
@@ -11,7 +11,7 @@ class Skr.Components.SkuFinder extends Lanes.React.Component
11
11
  getDefaultProps: ->
12
12
  autoFocus: false, label: 'SKU', name: 'code'
13
13
 
14
- dataObjects:
14
+ modelBindings:
15
15
  query: ->
16
16
  new Lanes.Models.Query({
17
17
  syncOptions: @props.syncOptions, autoRetrieve: true
@@ -1,6 +1,9 @@
1
1
  class Skr.Components.SystemSettings extends Lanes.React.Component
2
2
 
3
- dataObjects:
3
+ propTypes:
4
+ settings: React.PropTypes.object.isRequired
5
+
6
+ modelBindings:
4
7
  banks: ->
5
8
  Skr.Models.BankAccount.Collection.fetch()
6
9
  sequentialIds: ->
@@ -9,7 +9,7 @@ class Skr.Components.TermsChooser extends Lanes.React.Component
9
9
  getDefaultProps: ->
10
10
  label: 'Payment Terms', name: 'terms'
11
11
 
12
- dataObjects:
12
+ modelBindings:
13
13
  query: ->
14
14
  new Lanes.Models.Query({
15
15
  syncOptions: @props.syncOptions, autoRetrieve: true
@@ -36,5 +36,5 @@ class Skr.Components.TermsChooser extends Lanes.React.Component
36
36
  choices={Skr.Models.PaymentTerm.all.models}
37
37
  labelField="code"
38
38
  {...@props}
39
- fetchWhenOpen={false}
39
+ fetchOnSelect={false}
40
40
  model={@props.model} />
@@ -1,7 +1,11 @@
1
1
  class Skr.Components.ToolbarButton extends Lanes.React.BaseComponent
2
2
 
3
+ propTypes:
4
+ onClick: React.PropTypes.func.isRequired
5
+ className: React.PropTypes.string
6
+
3
7
  render: ->
4
- cn = _.classnames "navbar-btn", "control", @props.classNames
5
- <BS.Button navItem componentClass="button" {...@props} className={cn}>
8
+ cn = _.classnames "navbar-btn", "control", @props.className
9
+ <BS.NavItem onClick={@props.onClick} className={cn}>
6
10
  {@props.children}
7
- </BS.Button>
11
+ </BS.NavItem>
@@ -5,12 +5,16 @@ class Skr.Components.TotalsLine extends Lanes.React.Component
5
5
  attribute: React.PropTypes.string
6
6
  label: React.PropTypes.string
7
7
 
8
+
8
9
  getDefaultProps: ->
9
10
  attribute: 'total', label: 'Total:'
10
11
 
11
12
  render: ->
12
13
  <BS.Row className='totals'>
13
- <BS.Col lg=11 sm=10 xs=9 className="text-right">
14
+ <BS.Col lg=10 sm=9 xs=8 className="text-right">
15
+ {@props.extraInfo}
16
+ </BS.Col>
17
+ <BS.Col xs=1 className="text-right">
14
18
  <h4>{@props.label}</h4>
15
19
  </BS.Col>
16
20
  <BS.Col lg=1 sm=2 xs=3 className="total">
@@ -1,5 +1,5 @@
1
1
  class Skr.Components.UserPreferences extends Lanes.React.Component
2
- dataObjects:
2
+ modelBindings:
3
3
  user: -> Lanes.current_user
4
4
  projects: -> new Skr.Models.CustomerProject.Collection
5
5
 
@@ -10,7 +10,7 @@ class Skr.Components.VendorFinder extends Lanes.React.Component
10
10
  getDefaultProps: ->
11
11
  autoFocus: false, name: 'vendor', label: 'Vendor Code'
12
12
 
13
- dataObjects:
13
+ modelBindings:
14
14
  query: ->
15
15
  new Lanes.Models.Query({
16
16
  title: 'Vendors'
@@ -1,7 +1,20 @@
1
1
  class Skr.Components.Address extends Lanes.React.Component
2
2
 
3
3
  propTypes:
4
+ title: React.PropTypes.string
4
5
  model: Lanes.PropTypes.State.isRequired
6
+ copyFrom: Lanes.PropTypes.State
7
+
8
+ modelBindings:
9
+ model: 'props'
10
+ copyFrom: -> @props.copyFrom or false
11
+
12
+ setModelState: (addr) ->
13
+ if (addr is @props.copyFrom)
14
+ for attr, val of addr.changedAttributes() when attr isnt 'isDirty'
15
+ @model[attr] = val if addr.previous(attr) is @model[attr]
16
+ else
17
+ @forceUpdate()
5
18
 
6
19
  renderTitle: ->
7
20
  <BS.Row>
@@ -11,7 +24,7 @@ class Skr.Components.Address extends Lanes.React.Component
11
24
  </BS.Row>
12
25
 
13
26
  render: ->
14
- colProps = _.omit(@props, 'name')
27
+ colProps = _.omit(@props, _.keys(@constructor.propTypes))
15
28
  colProps.className = _.classnames("address", @props.className)
16
29
 
17
30
  <BS.Col {...colProps}>
@@ -14,3 +14,9 @@
14
14
  margin-left: 5px;
15
15
  }
16
16
  }
17
+
18
+
19
+ .totals.row {
20
+ display: flex;
21
+ align-items: baseline;
22
+ }
@@ -1,6 +1,7 @@
1
1
  //=require ./models/Base
2
2
  //=require ./screens/Base
3
3
  //=require ./screens/Commands
4
+ //=require ./lib
4
5
  //=require_tree ./models/mixins
5
6
  //=require_tree ./models
6
7
  //=require_tree ./components
@@ -0,0 +1,32 @@
1
+ readLoadUrl = (matchRegex) ->
2
+ src = document.createElement('a')
3
+ for tag in document.querySelectorAll('script')
4
+ if tag.src.match matchRegex
5
+ src.href = tag.src
6
+ Lanes.config.api_host = src.host
7
+ break
8
+ if Lanes.config.api_host
9
+ css = src.href.replace(/\.js$/, '.css')
10
+ new Lanes.lib.AssetLoader([css], Lanes.emptyFn)
11
+ else
12
+ console.error("Unable to find script tag that Stockor was loaded from")
13
+
14
+
15
+ Skr.lib.Remote = {
16
+
17
+ onDocumentReady: (fn) ->
18
+ if document.readyState isnt 'loading'
19
+ fn()
20
+ else if document.addEventListener
21
+ document.addEventListener 'DOMContentLoaded', fn
22
+ else
23
+ document.attachEvent 'onreadystatechange', ->
24
+ fn() if document.readyState != 'loading'
25
+
26
+ configFromScriptTag: (matchRegex = /\/assets\/skr\/api\.js$/) ->
27
+ new _.Promise (resolve) ->
28
+ Skr.lib.Remote.onDocumentReady ->
29
+ readLoadUrl(matchRegex)
30
+ resolve(Lanes.config)
31
+
32
+ }
@@ -0,0 +1,2 @@
1
+ //= require ./namespace
2
+ //= require ./Remote
@@ -0,0 +1 @@
1
+ Skr.lib ||= {}
@@ -1,6 +1,6 @@
1
1
  class Skr.Models.CreditCardGateway extends Skr.Models.Base
2
2
 
3
- pubsub: false
3
+ registerForPubSub: false
4
4
 
5
5
  props:
6
6
  login: "string"
@@ -0,0 +1,11 @@
1
+ class Skr.Models.ExpenseCategory extends Skr.Models.Base
2
+
3
+ props:
4
+ id: {"type":"integer"}
5
+ code: {"type":"code", "required":true}
6
+ name: {"type":"string", "required":true}
7
+ is_active: {"type":"boolean", "required":true, default: true}
8
+ gl_account_id:{"type":"integer", "required":true}
9
+
10
+ associations:
11
+ gl_account: { model: "GlAccount" }
@@ -0,0 +1,64 @@
1
+ class ExpenseAssets extends Lanes.Models.AssociationCollection
2
+
3
+
4
+ comparator: (a) -> ! a.isPresent
5
+
6
+ constructor: ->
7
+ super
8
+ @listenTo(@parent, 'save', @onSave)
9
+ @on('change:length', @ensureBlank)
10
+ @on('change:isPresent', @ensureBlank)
11
+ @ensureBlank()
12
+ @present = @subcollection(watched: ['isPresent'], filter: (m) ->
13
+ m.isPresent
14
+ )
15
+
16
+
17
+ getId: -> @parent.getId()
18
+ modelTypeIdentifier: -> @parent.modelTypeIdentifier()
19
+ extensionIdentifier: -> @parent.extensionIdentifier()
20
+
21
+ ensureBlank: ->
22
+ blank = @find( (asset) -> !asset.isPresent )
23
+ @add({}) unless blank
24
+
25
+ onSave: ->
26
+ @each (asset) -> asset.save()
27
+
28
+ _prepareModel: (attrs, options) ->
29
+ attrs.parent || = @
30
+ attrs.parent_association = @options.association_name
31
+ super
32
+
33
+
34
+ class Skr.Models.ExpenseEntry extends Skr.Models.Base
35
+
36
+ props:
37
+ id: {type:"integer"}
38
+ uuid: {"type":"string"}
39
+ name: {"type":"string", "required":true}
40
+ occured: {"type":"date", "required":true}
41
+ gl_transaction_id: "integer"
42
+ memo: "string"
43
+ expense_category_id: {"type":"integer", "required":true}
44
+
45
+ session:
46
+ category_total: type:"bigdec", "required":true
47
+ category_list: type: "object"
48
+ gl_transaction_ids: type: 'array'
49
+ category_ids: type: 'array'
50
+
51
+ associations:
52
+ categories: { collection: "ExpenseEntryCategory", inverse: 'entry' }
53
+ gl_transaction: { model: "GlTransaction" }
54
+ attachments: { collection: "Lanes.Models.Asset", options: { 'collectionClass': ExpenseAssets } }
55
+
56
+ dataForSave: ->
57
+ super(includeAssociations: [
58
+ 'categories'
59
+ ])
60
+
61
+ total: ->
62
+ @categories.reduce (amt, cat) ->
63
+ cat.amount.add(amt)
64
+ , _.bigDecimal('0')
@@ -0,0 +1,11 @@
1
+ class Skr.Models.ExpenseEntryCategory extends Skr.Models.Base
2
+
3
+ props:
4
+ id: {"type":"any", "required":true}
5
+ entry_id: "integer"
6
+ category_id: {"type":"integer", "required":true}
7
+ amount: {"type":"bigdec"}
8
+
9
+ associations:
10
+ category: { model: "ExpenseCategory" }
11
+ entry: { model: "ExpenseEntry" }
@@ -25,11 +25,14 @@ class Skr.Models.Invoice extends Skr.Models.Base
25
25
 
26
26
  mixins: [ 'HasVisibleId', 'PrintSupport' ]
27
27
 
28
- # optional attributes from details view
28
+ # optional attributes from details view and other fields
29
29
  session:
30
30
  customer_code: {type:"string"}
31
+ customer_name: {type:"string"}
31
32
  invoice_total: {type:"bigdec"}
32
33
  amount_paid: {type:"bigdec", "default":"0"}
34
+ total_hours: "bigdec"
35
+ num_lines: {type:"integer"}
33
36
 
34
37
  derived:
35
38
  prev_amount_paid: deps:['updated_at'], fn: -> @amount_paid