stockor 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -4
- data/Gemfile.lock +104 -87
- data/client/skr/api.js +3 -1
- data/client/skr/api/Components/AddressForm.cjsx +1 -1
- data/client/skr/api/Components/SingleItemCart.cjsx +1 -1
- data/client/skr/api/SingleItemCheckout.cjsx +3 -3
- data/client/skr/components/BankAccountFinder.cjsx +1 -1
- data/client/skr/components/CreditCardForm.cjsx +1 -1
- data/client/skr/components/Currency.cjsx +2 -1
- data/client/skr/components/CustomerFinder.cjsx +1 -1
- data/client/skr/components/CustomerProjectFinder.cjsx +1 -1
- data/client/skr/components/ExpenseCategoryFinder.cjsx +34 -0
- data/client/skr/components/GlAccountChooser.cjsx +2 -1
- data/client/skr/components/InvoiceFinder.cjsx +1 -1
- data/client/skr/components/LatexSnippets.cjsx +3 -0
- data/client/skr/components/LocationChooser.cjsx +3 -3
- data/client/skr/components/PaymentCategoryFinder.cjsx +1 -1
- data/client/skr/components/SalesOrderFinder.cjsx +1 -2
- data/client/skr/components/SkuFinder.cjsx +1 -1
- data/client/skr/components/SystemSettings.cjsx +4 -1
- data/client/skr/components/TermsChooser.cjsx +2 -2
- data/client/skr/components/ToolbarButton.cjsx +7 -3
- data/client/skr/components/TotalsLine.cjsx +5 -1
- data/client/skr/components/UserPreferences.cjsx +1 -1
- data/client/skr/components/VendorFinder.cjsx +1 -1
- data/client/skr/components/address/Address.cjsx +14 -1
- data/client/skr/components/styles.scss +6 -0
- data/client/skr/index.js +1 -0
- data/client/skr/lib/Remote.coffee +32 -0
- data/client/skr/lib/index.js +2 -0
- data/client/skr/lib/namespace.coffee +1 -0
- data/client/skr/models/CreditCardGateway.coffee +1 -1
- data/client/skr/models/ExpenseCategory.coffee +11 -0
- data/client/skr/models/ExpenseEntry.coffee +64 -0
- data/client/skr/models/ExpenseEntryCategory.coffee +11 -0
- data/client/skr/models/Invoice.coffee +4 -1
- data/client/skr/models/Payment.coffee +2 -2
- data/client/skr/models/SalesOrder.coffee +3 -2
- data/client/skr/models/SequentialId.coffee +1 -1
- data/client/skr/models/Vendor.coffee +1 -1
- data/client/skr/models/mixins/PrintSupport.coffee +1 -1
- data/client/skr/screens/bank-maint/BankMaint.cjsx +1 -1
- data/client/skr/screens/chart-of-accounts/ChartOfAccounts.cjsx +1 -1
- data/client/skr/screens/customer-maint/CustomerMaint.cjsx +1 -1
- data/client/skr/screens/customer-projects/CustomerProjects.cjsx +1 -1
- data/client/skr/screens/expense-categories/ExpenseCategories.cjsx +31 -0
- data/client/skr/screens/expense-categories/index.js +5 -0
- data/client/skr/screens/expense-categories/index.scss +9 -0
- data/client/skr/screens/expense-entry/ApprovalRequest.coffee +14 -0
- data/client/skr/screens/expense-entry/ApproveDialog.cjsx +30 -0
- data/client/skr/screens/expense-entry/Categories.cjsx +112 -0
- data/client/skr/screens/expense-entry/ExpenseEntry.cjsx +193 -0
- data/client/skr/screens/expense-entry/Form.cjsx +54 -0
- data/client/skr/screens/expense-entry/Grid.cjsx +51 -0
- data/client/skr/screens/expense-entry/ScreenState.coffee +1 -0
- data/client/skr/screens/expense-entry/index.js +1 -0
- data/client/skr/screens/expense-entry/index.scss +106 -0
- data/client/skr/screens/fresh-books-import/ApiInfo.cjsx +3 -3
- data/client/skr/screens/fresh-books-import/ChooseRecords.cjsx +6 -4
- data/client/skr/screens/fresh-books-import/FreshBooksImport.cjsx +1 -1
- data/client/skr/screens/fresh-books-import/ViewRecords.cjsx +2 -2
- data/client/skr/screens/fresh-books-import/index.scss +5 -4
- data/client/skr/screens/gl-accounts/GlAccounts.cjsx +1 -1
- data/client/skr/screens/gl-transactions/GlTransactions.cjsx +1 -1
- data/client/skr/screens/invoice/Invoice.cjsx +6 -2
- data/client/skr/screens/invoice/Payment.cjsx +1 -1
- data/client/skr/screens/invoice/TotalExtraInfo.cjsx +32 -0
- data/client/skr/screens/invoice/index.scss +4 -2
- data/client/skr/screens/locations/Locations.cjsx +1 -1
- data/client/skr/screens/payment-category/PaymentCategory.cjsx +1 -1
- data/client/skr/screens/payment-terms/PaymentTerms.cjsx +1 -1
- data/client/skr/screens/payments/Payments.cjsx +13 -6
- data/client/skr/screens/sale-report/SaleReport.cjsx +1 -1
- data/client/skr/screens/sales-order/SalesOrder.cjsx +2 -1
- data/client/skr/screens/sku-maint/SkuMaint.cjsx +1 -1
- data/client/skr/screens/sku-maint/SkuUomList.cjsx +2 -2
- data/client/skr/screens/time-invoicing/TimeInvoicing.cjsx +4 -4
- data/client/skr/screens/time-tracking/EditEntry.cjsx +2 -2
- data/client/skr/screens/time-tracking/Entries.coffee +6 -4
- data/client/skr/screens/time-tracking/Popover.cjsx +11 -6
- data/client/skr/screens/time-tracking/TimeTracking.cjsx +12 -5
- data/client/skr/screens/vendor-maint/VendorMaint.cjsx +2 -2
- data/config/database.yml +2 -0
- data/config/puma.rb +0 -4
- data/config/routes.rb +4 -0
- data/config/screens.rb +17 -0
- data/db/migrate/20140323001446_create_so_details_view.rb +2 -2
- data/db/migrate/20151121211323_create_customer_project_details_views.rb +1 -1
- data/db/migrate/20160216142845_create_gl_account_balances_view.rb +1 -1
- data/db/migrate/20160726004411_string_check_numbers.rb +5 -0
- data/db/migrate/20160805002717_create_expenses.rb +65 -0
- data/db/schema.sql +394 -229
- data/db/seed.rb +12 -12
- data/lib/skr/access_roles.rb +9 -4
- data/lib/skr/concerns/has_gl_transaction.rb +1 -1
- data/lib/skr/configuration.rb +3 -1
- data/lib/skr/db/migration_helpers.rb +2 -2
- data/lib/skr/handlers/approve_expense_entries.rb +16 -0
- data/lib/skr/handlers/invoice_from_time_entries.rb +1 -1
- data/lib/skr/handlers/sequential_ids.rb +2 -2
- data/lib/skr/jobs/fresh_books/import.rb +18 -17
- data/lib/skr/model.rb +3 -0
- data/lib/skr/models/bank_account.rb +9 -0
- data/lib/skr/models/expense_category.rb +27 -0
- data/lib/skr/models/expense_entry.rb +76 -0
- data/lib/skr/models/expense_entry_category.rb +15 -0
- data/lib/skr/models/gl_transaction.rb +2 -2
- data/lib/skr/models/inv_line.rb +3 -1
- data/lib/skr/models/invoice.rb +9 -5
- data/lib/skr/models/payment.rb +1 -1
- data/lib/skr/models/purchase_order.rb +4 -4
- data/lib/skr/models/uom.rb +2 -2
- data/lib/skr/models/voucher.rb +4 -4
- data/lib/skr/print/form.rb +17 -14
- data/lib/skr/version.rb +1 -1
- data/spec/fixtures/skr/expense_category.yml +17 -0
- data/spec/fixtures/skr/expense_entries.yml +20 -0
- data/spec/fixtures/skr/expense_entry_category.yml +19 -0
- data/spec/fixtures/skr/gl_account.yml +10 -0
- data/spec/server/handlers/invoice_from_time_entries_spec.rb +2 -2
- data/spec/server/handlers/sequential_ids_spec.rb +1 -1
- data/spec/server/models/expense_category_spec.rb +17 -0
- data/spec/server/models/expense_entry_spec.rb +44 -0
- data/spec/server/models/invoice_spec.rb +0 -1
- data/spec/server/models/spec_helper_spec.rb +5 -10
- data/spec/server/spec_helper.rb +12 -11
- data/spec/skr/components/SkuLinesSpec.coffee +11 -9
- data/spec/skr/models/CustomerSpec.coffee +1 -1
- data/spec/skr/models/ExpenseAccountSpec.coffee +5 -0
- data/spec/skr/screens/expense-categories/ExpenseCategoriesSpec.coffee +5 -0
- data/spec/skr/screens/expense-entry/ExpenseEntrySpec.coffee +5 -0
- data/spec/skr/screens/locations/LocationsSpec.coffee +4 -4
- data/spec/skr/screens/time-tracking/TimeTrackingSpec.coffee +4 -4
- data/stockor.gemspec +2 -3
- data/templates/print/partials/header.tex.erb +1 -1
- data/templates/print/partials/skus_table_invoice_footer.tex.erb +22 -19
- data/templates/print/partials/skus_table_invoice_info_line.tex.erb +5 -1
- data/templates/print/types/payment/default.tex.erb +10 -10
- metadata +40 -14
- data/client/skr/api/onReady.coffee +0 -23
- data/spec/skr/api/SingleItemCheckoutSpec.cjsx +0 -10
- data/spec/skr/screens/bank-maint/BankMaintSpec.coffee +0 -5
- data/spec/skr/screens/gl-accounts/GlAccountsSpec.coffee +0 -5
- data/spec/skr/screens/invoice/InvoiceSpec.coffee +0 -5
- data/spec/skr/screens/payment-category/PaymentCategorySpec.coffee +0 -5
- data/spec/skr/screens/payments/PaymentsSpec.coffee +0 -5
- data/spec/skr/screens/sale-report/SaleReportSpec.coffee +0 -5
@@ -0,0 +1,54 @@
|
|
1
|
+
class Attachments extends Lanes.React.Component
|
2
|
+
modelBindings:
|
3
|
+
attachments: 'props'
|
4
|
+
|
5
|
+
render: ->
|
6
|
+
<LC.FieldSet
|
7
|
+
title={"Attachments (#{@attachments.length-1})"}
|
8
|
+
>
|
9
|
+
<LC.AssetsListing assets={@attachments}
|
10
|
+
name='attachments' size="thumb" />
|
11
|
+
</LC.FieldSet>
|
12
|
+
|
13
|
+
class Skr.Screens.ExpenseEntry.Form extends Lanes.React.Component
|
14
|
+
|
15
|
+
propTypes:
|
16
|
+
onEntrySave: React.PropTypes.func.isRequired
|
17
|
+
|
18
|
+
modelBindings:
|
19
|
+
entry: 'props'
|
20
|
+
|
21
|
+
getInitialState: ->
|
22
|
+
isEditing: true
|
23
|
+
|
24
|
+
mixins: [
|
25
|
+
Lanes.React.Mixins.RelayEditingState
|
26
|
+
]
|
27
|
+
|
28
|
+
focus: ->
|
29
|
+
_.defer => @refs.name.focus()
|
30
|
+
|
31
|
+
render: ->
|
32
|
+
<div className="form">
|
33
|
+
<LC.NetworkActivityOverlay model={@entry} />
|
34
|
+
<BS.Row>
|
35
|
+
<LC.Input sm=8 name='name' ref="name" model={@entry} />
|
36
|
+
<Skr.Screens.ExpenseEntry.Categories
|
37
|
+
categories={@props.categories}
|
38
|
+
entry={@entry} sm={4} />
|
39
|
+
</BS.Row>
|
40
|
+
|
41
|
+
<BS.Row>
|
42
|
+
<Attachments attachments={@entry.attachments} />
|
43
|
+
</BS.Row>
|
44
|
+
|
45
|
+
<BS.Row>
|
46
|
+
<LC.Input sm=10 name='memo' model={@entry} />
|
47
|
+
<LC.FormGroup className='controls' sm=2>
|
48
|
+
<BS.ButtonGroup>
|
49
|
+
<BS.Button tabIndex={-1} onClick={@props.onEntryReset}>Reset</BS.Button>
|
50
|
+
<BS.Button onClick={@props.onEntrySave}>Save</BS.Button>
|
51
|
+
</BS.ButtonGroup>
|
52
|
+
</LC.FormGroup>
|
53
|
+
</BS.Row>
|
54
|
+
</div>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Skr.Screens.ExpenseEntry.Grid extends Lanes.React.Component
|
2
|
+
|
3
|
+
propTypes:
|
4
|
+
onRecordSelect: React.PropTypes.func.isRequired
|
5
|
+
|
6
|
+
modelBindings:
|
7
|
+
categories: 'props'
|
8
|
+
query: 'props'
|
9
|
+
|
10
|
+
getInitialState: ->
|
11
|
+
category: new Skr.Models.ExpenseCategory
|
12
|
+
|
13
|
+
getCurrentCategory: -> @state.category
|
14
|
+
|
15
|
+
renderReviewCheckbox: ->
|
16
|
+
return null unless Lanes.current_user.roles.includes('accounting')
|
17
|
+
<BS.Checkbox className="all-users" checked={!!@query.syncOptions.queryParams?.review}
|
18
|
+
onChange={(ev) => @props.setReviewState(ev.target.checked)}
|
19
|
+
> Review</BS.Checkbox>
|
20
|
+
|
21
|
+
renderApproveToggle: ->
|
22
|
+
return null unless @props.isReviewing
|
23
|
+
<span className="approved-toggle">
|
24
|
+
<LC.IndeterminateCheckbox checked={@props.isConfirmationChecked}
|
25
|
+
onChange={(ev) => @props.onConfirmationToggle(ev.target.checked)}
|
26
|
+
/>
|
27
|
+
</span>
|
28
|
+
|
29
|
+
toolbarControls: ->
|
30
|
+
<BS.Navbar.Form className="controls">
|
31
|
+
{@renderApproveToggle()}
|
32
|
+
<div className="spacer" />
|
33
|
+
<div className="right">
|
34
|
+
{@renderReviewCheckbox()}
|
35
|
+
<SC.ExpenseCategoryFinder
|
36
|
+
choices={@categories.models} fetchOnSelect={false}
|
37
|
+
withClearBtn fieldOnly editOnly selectField unlabeled
|
38
|
+
model={@state.category} getSelection={@getCurrentCategory}
|
39
|
+
setSelection={@props.onCategorySelect} />
|
40
|
+
</div>
|
41
|
+
</BS.Navbar.Form>
|
42
|
+
|
43
|
+
render: ->
|
44
|
+
<LC.Grid
|
45
|
+
expandY={true}
|
46
|
+
onColumnClick={@onColumnSort}
|
47
|
+
isRowFocused={@props.isRowFocused}
|
48
|
+
query={@query} height=200 autoLoadQuery
|
49
|
+
onSelectionChange={@props.onRecordSelect}
|
50
|
+
toolbarChildren={@toolbarControls()}
|
51
|
+
/>
|
@@ -0,0 +1 @@
|
|
1
|
+
class Skr.Screens.ExpenseEntry.ScreenState extends Lanes.Models.State
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require ./ExpenseEntry
|
@@ -0,0 +1,106 @@
|
|
1
|
+
/*
|
2
|
+
You should remove this file if your screen does not use any custom styles
|
3
|
+
|
4
|
+
Otherwise Lanes will continue to fetch an empty file whenever
|
5
|
+
the screen is displayed
|
6
|
+
*/
|
7
|
+
.expense-entry {
|
8
|
+
$first-column-width: 90px;
|
9
|
+
.footer {
|
10
|
+
display: none;
|
11
|
+
button {
|
12
|
+
width: $first-column-width;
|
13
|
+
border-top-left-radius: 0;
|
14
|
+
border-top-right-radius: 0;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
&.is-reviewing {
|
18
|
+
.footer { display: block; }
|
19
|
+
}
|
20
|
+
|
21
|
+
.selection {
|
22
|
+
//margin: 5px;
|
23
|
+
}
|
24
|
+
|
25
|
+
.form {
|
26
|
+
.controls {
|
27
|
+
text-align: center;
|
28
|
+
}
|
29
|
+
|
30
|
+
}
|
31
|
+
|
32
|
+
.grid-component .toolbar .controls {
|
33
|
+
display: flex;
|
34
|
+
justify-content: space-around;
|
35
|
+
align-items: center;
|
36
|
+
.approved-toggle {
|
37
|
+
width: $first-column-width;
|
38
|
+
text-align: center;
|
39
|
+
}
|
40
|
+
.all-users {
|
41
|
+
margin-right: 20px;
|
42
|
+
}
|
43
|
+
.spacer { flex: 1; }
|
44
|
+
}
|
45
|
+
|
46
|
+
|
47
|
+
.categories {
|
48
|
+
display: flex;
|
49
|
+
align-items: flex-end;
|
50
|
+
position: relative;
|
51
|
+
.add { margin-left: 5px; }
|
52
|
+
.multiple {
|
53
|
+
.controls {
|
54
|
+
display: flex;
|
55
|
+
align-items: center;
|
56
|
+
justify-content: flex-end;
|
57
|
+
p {
|
58
|
+
flex: 1;
|
59
|
+
.pair + .pair { margin-left: 0.5em; }
|
60
|
+
}
|
61
|
+
.btn.view {
|
62
|
+
margin-right: 1em;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
.form-control-static { padding-top: 0; padding-bottom: 0; }
|
66
|
+
.pair {
|
67
|
+
max-width: 100px;
|
68
|
+
display: inline-block;
|
69
|
+
text-overflow: ellipsis;
|
70
|
+
overflow: hidden;
|
71
|
+
white-space: nowrap;
|
72
|
+
max-height: 35px;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
.category {
|
77
|
+
display: flex;
|
78
|
+
align-items: center;
|
79
|
+
margin-bottom: 15px;
|
80
|
+
.form-group { margin-bottom: 0; }
|
81
|
+
.lanes-field { flex: 1; }
|
82
|
+
.btn {
|
83
|
+
margin-left: 0.5rem;
|
84
|
+
&.delete { display: none; }
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
.popover-content {
|
89
|
+
width: 320px;
|
90
|
+
.category {
|
91
|
+
label { display: none; }
|
92
|
+
.btn.delete { display: block; }
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
#choose-bank-account {
|
98
|
+
.popover-content {
|
99
|
+
display: flex;
|
100
|
+
button { margin-left: 0.5rem; }
|
101
|
+
}
|
102
|
+
|
103
|
+
//height: 200px;
|
104
|
+
|
105
|
+
}
|
106
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Skr.Screens.FreshBooksImport.ApiInfo extends Lanes.React.Component
|
2
2
|
listenNetworkEvents: true
|
3
|
-
|
3
|
+
modelBindings:
|
4
4
|
import: 'props'
|
5
5
|
startImport: ->
|
6
6
|
@import.save()
|
@@ -20,10 +20,10 @@ class Skr.Screens.FreshBooksImport.ApiInfo extends Lanes.React.Component
|
|
20
20
|
<p>Your access information will not be stored and is only used to download records</p>
|
21
21
|
</BS.Col>
|
22
22
|
</BS.Row>
|
23
|
-
<BS.Row>
|
23
|
+
<BS.Row className="api-info">
|
24
24
|
<LC.Input name='api_key' label='API Key' sm=7 model={@import} />
|
25
25
|
<LC.Input name='domain' label='Company' sm=3 model={@import} />
|
26
|
-
<BS.
|
26
|
+
<BS.Col sm=2 className="domain">.freshbooks.com</BS.Col>
|
27
27
|
</BS.Row>
|
28
28
|
<BS.Row>
|
29
29
|
<BS.Col smOffset=9 sm=2>
|
@@ -11,7 +11,7 @@ class TextInput extends Lanes.React.Component
|
|
11
11
|
<input value={@props.row.customer_code || ''} onChange={@setCode} />
|
12
12
|
|
13
13
|
class UserSelect extends Lanes.React.Component
|
14
|
-
|
14
|
+
modelBindings:
|
15
15
|
user: -> new Lanes.Models.User
|
16
16
|
|
17
17
|
getUser: ->
|
@@ -58,7 +58,7 @@ class RecordRow extends Lanes.React.BaseComponent
|
|
58
58
|
|
59
59
|
class Skr.Screens.FreshBooksImport.ChooseRecords extends Lanes.React.Component
|
60
60
|
listenNetworkEvents: true
|
61
|
-
|
61
|
+
modelBindings:
|
62
62
|
import: 'props'
|
63
63
|
job: -> @props.import.job
|
64
64
|
|
@@ -107,9 +107,11 @@ class Skr.Screens.FreshBooksImport.ChooseRecords extends Lanes.React.Component
|
|
107
107
|
return null unless @import.hasPendingRecords()
|
108
108
|
<div className="import-records">
|
109
109
|
{@renderHeader()}
|
110
|
-
<BS.Tabs
|
110
|
+
<BS.Tabs id='choose-records'>
|
111
111
|
{for type, i in @import.recordTypes when @import.recordsForType(type)
|
112
|
-
<BS.Tab eventKey={i} key={i}
|
112
|
+
<BS.Tab eventKey={i} key={i}
|
113
|
+
title={_.titleize(type)} animation={false}
|
114
|
+
>
|
113
115
|
<@RecordTable type={type} />
|
114
116
|
</BS.Tab>}
|
115
117
|
</BS.Tabs>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# coffeelint: disable=max_line_length
|
2
2
|
class Skr.Screens.FreshBooksImport.ViewRecords extends Lanes.React.Component
|
3
3
|
listenNetworkEvents: true
|
4
|
-
|
4
|
+
modelBindings:
|
5
5
|
import: 'props'
|
6
6
|
job: -> @props.import.job
|
7
7
|
|
@@ -87,7 +87,7 @@ class Skr.Screens.FreshBooksImport.ViewRecords extends Lanes.React.Component
|
|
87
87
|
return null unless @import.hasImportedRecords()
|
88
88
|
|
89
89
|
<h3>Import Success!</h3>
|
90
|
-
<BS.Tabs
|
90
|
+
<BS.Tabs id='view-records'>
|
91
91
|
{for type, i in @import.recordTypes
|
92
92
|
TableType = @[_.capitalize(type)] || @BlankTable
|
93
93
|
<BS.Tab eventKey={i} key={i} title={_.titleize(type)} animation={false}>
|
@@ -1,12 +1,13 @@
|
|
1
1
|
.fresh-books-import {
|
2
|
-
.domain .value {
|
3
|
-
margin-top: 15px;
|
4
|
-
}
|
5
2
|
.job-executing {
|
6
3
|
width: 80%;
|
7
4
|
margin: 80px auto;
|
8
5
|
}
|
9
|
-
|
6
|
+
.api-info {
|
7
|
+
.domain {
|
8
|
+
padding-top: 35px;
|
9
|
+
}
|
10
|
+
}
|
10
11
|
.import-records {
|
11
12
|
.clients tbody tr td:last-child {
|
12
13
|
width: 130px;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
##= require_self
|
2
2
|
##= require ./Payment
|
3
|
+
##= require ./TotalExtraInfo
|
3
4
|
|
4
5
|
class Skr.Screens.Invoice extends Skr.Screens.Base
|
5
6
|
|
@@ -7,7 +8,7 @@ class Skr.Screens.Invoice extends Skr.Screens.Base
|
|
7
8
|
with: [ 'with_details' ]
|
8
9
|
include: [ 'sales_order', 'billing_address', 'shipping_address', 'lines', 'payments' ]
|
9
10
|
|
10
|
-
|
11
|
+
modelBindings:
|
11
12
|
invoice: ->
|
12
13
|
@loadOrCreateModel({
|
13
14
|
syncOptions: @syncOptions, klass: Skr.Models.Invoice,
|
@@ -49,6 +50,7 @@ class Skr.Screens.Invoice extends Skr.Screens.Base
|
|
49
50
|
parentModel={@invoice} />
|
50
51
|
|
51
52
|
<SC.CustomerFinder
|
53
|
+
fallBackValue={@invoice.customer_code}
|
52
54
|
syncOptions={ include: ['billing_address', 'shipping_address' ] }
|
53
55
|
selectField sm=3 xs=6 model={@invoice} />
|
54
56
|
|
@@ -87,5 +89,7 @@ class Skr.Screens.Invoice extends Skr.Screens.Base
|
|
87
89
|
saveImmediately={@shouldSaveLinesImmediately}
|
88
90
|
commands={@state.commands} lines={@invoice.lines} />
|
89
91
|
|
90
|
-
<SC.TotalsLine model={@invoice}
|
92
|
+
<SC.TotalsLine model={@invoice} extraInfo={
|
93
|
+
<Skr.Screens.Invoice.TotalExtraInfo invoice={@invoice} />
|
94
|
+
} />
|
91
95
|
</LC.ScreenWrapper>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Skr.Screens.Invoice.TotalExtraInfo extends Lanes.React.Component
|
2
|
+
|
3
|
+
modelBindings:
|
4
|
+
invoice: 'props'
|
5
|
+
|
6
|
+
checkLoading: ->
|
7
|
+
unless @invoice.total_hours
|
8
|
+
@invoice.fetch({
|
9
|
+
fields: ['total_hours']
|
10
|
+
})
|
11
|
+
|
12
|
+
TotalHours: ->
|
13
|
+
body = if @invoice.total_hours
|
14
|
+
<span>Hours: {Lanes.u.format.currency(@invoice.total_hours)}</span>
|
15
|
+
else
|
16
|
+
[
|
17
|
+
<LC.Icon key="icon" type='spinner' />,
|
18
|
+
<span key='msg'> Loading...</span>
|
19
|
+
]
|
20
|
+
<div className="invoice-total-hours-tooltip">
|
21
|
+
{body}
|
22
|
+
</div>
|
23
|
+
|
24
|
+
|
25
|
+
render: ->
|
26
|
+
return null if @invoice.form isnt 'labor' or @invoice.isNew()
|
27
|
+
|
28
|
+
<LC.Icon
|
29
|
+
className='total-hours'
|
30
|
+
tooltipProps={onEntering: @checkLoading}
|
31
|
+
type='clock-o' tooltip={<@TotalHours />}
|
32
|
+
/>
|