stockor 0.1.9 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +254 -72
- data/Guardfile +1 -1
- data/README.md +24 -3
- data/app.json +28 -0
- data/client/skr/Extension.coffee +18 -0
- data/client/skr/components/BankAccountFinder.cjsx +34 -0
- data/client/skr/components/Currency.cjsx +19 -0
- data/client/skr/components/CustomerFinder.cjsx +37 -0
- data/client/skr/components/CustomerLink.cjsx +13 -0
- data/client/skr/components/CustomerProjectFinder.cjsx +49 -0
- data/client/skr/components/GlAccountChooser.cjsx +38 -0
- data/client/skr/components/InvoiceFinder.cjsx +37 -0
- data/client/skr/components/InvoiceLink.cjsx +13 -0
- data/client/skr/components/LocationChooser.cjsx +37 -0
- data/client/skr/components/PaymentCategoryFinder.cjsx +34 -0
- data/client/skr/components/PrintFormChooser.cjsx +29 -0
- data/client/skr/components/SalesOrderFinder.cjsx +38 -0
- data/client/skr/components/ScreenControls.cjsx +20 -0
- data/client/skr/components/SkuFinder.cjsx +30 -0
- data/client/skr/components/SkuLines.cjsx +76 -0
- data/client/skr/components/SystemSettings.cjsx +26 -0
- data/client/skr/components/TermsChooser.cjsx +40 -0
- data/client/skr/components/ToolbarButton.cjsx +7 -0
- data/client/skr/components/TotalsLine.cjsx +21 -0
- data/client/skr/components/TriStateIcon.cjsx +12 -0
- data/client/skr/components/UOMChooser.cjsx +24 -0
- data/client/skr/components/UserPreferences.cjsx +30 -0
- data/client/skr/components/VendorFinder.cjsx +40 -0
- data/client/skr/components/address/Address.cjsx +10 -10
- data/client/skr/components/styles.scss +16 -0
- data/client/skr/index.js +3 -1
- data/client/skr/models/Address.coffee +9 -1
- data/client/skr/models/BankAccount.coffee +17 -0
- data/client/skr/models/Base.coffee +6 -0
- data/client/skr/models/Customer.coffee +17 -10
- data/client/skr/models/CustomerProject.coffee +29 -0
- data/client/skr/models/GlAccount.coffee +22 -10
- data/client/skr/models/GlManualEntry.coffee +4 -2
- data/client/skr/models/GlPeriod.coffee +4 -6
- data/client/skr/models/GlPosting.coffee +7 -7
- data/client/skr/models/GlTransaction.coffee +3 -3
- data/client/skr/models/IaLine.coffee +9 -9
- data/client/skr/models/IaReason.coffee +4 -4
- data/client/skr/models/InvLine.coffee +30 -11
- data/client/skr/models/InventoryAdjustment.coffee +8 -6
- data/client/skr/models/Invoice.coffee +89 -18
- data/client/skr/models/Location.coffee +27 -6
- data/client/skr/models/Payment.coffee +36 -0
- data/client/skr/models/PaymentCategory.coffee +12 -0
- data/client/skr/models/PaymentTerm.coffee +17 -4
- data/client/skr/models/PickTicket.coffee +7 -5
- data/client/skr/models/PoLine.coffee +15 -15
- data/client/skr/models/PoReceipt.coffee +8 -6
- data/client/skr/models/PorLine.coffee +11 -11
- data/client/skr/models/PricingProvider.coffee +6 -0
- data/client/skr/models/PtLine.coffee +13 -13
- data/client/skr/models/PurchaseOrder.coffee +11 -9
- data/client/skr/models/SalesOrder.coffee +59 -22
- data/client/skr/models/Sku.coffee +17 -15
- data/client/skr/models/SkuLoc.coffee +14 -9
- data/client/skr/models/SkuTran.coffee +10 -10
- data/client/skr/models/SkuVendor.coffee +9 -9
- data/client/skr/models/SoLine.coffee +27 -20
- data/client/skr/models/TimeEntry.coffee +75 -0
- data/client/skr/models/Uom.coffee +27 -6
- data/client/skr/models/Vendor.coffee +14 -12
- data/client/skr/models/VoLine.coffee +11 -11
- data/client/skr/models/Voucher.coffee +7 -5
- data/client/skr/models/mixins/HasVisibleId.coffee +7 -0
- data/client/skr/models/mixins/PrintSupport.coffee +6 -0
- data/client/skr/models/mixins/SkuLine.coffee +61 -0
- data/client/skr/screens/Commands.coffee +29 -0
- data/client/skr/screens/bank-maint/BankMaint.cjsx +43 -0
- data/client/skr/screens/bank-maint/index.js +5 -0
- data/client/skr/screens/chart-of-accounts/ChartOfAccounts.cjsx +40 -0
- data/client/skr/screens/chart-of-accounts/index.js +1 -0
- data/client/skr/screens/chart-of-accounts/index.scss +12 -0
- data/client/skr/screens/customer-maint/CustomerMaint.cjsx +35 -36
- data/client/skr/screens/customer-projects/CustomerProjects.cjsx +70 -0
- data/client/skr/screens/customer-projects/index.js +5 -0
- data/client/skr/screens/customer-projects/index.scss +25 -0
- data/client/skr/screens/fresh-books-import/ApiInfo.cjsx +35 -0
- data/client/skr/screens/fresh-books-import/ChooseRecords.cjsx +116 -0
- data/client/skr/screens/fresh-books-import/FreshBooksImport.cjsx +31 -0
- data/client/skr/screens/fresh-books-import/Import.coffee +52 -0
- data/client/skr/screens/fresh-books-import/ViewRecords.cjsx +96 -0
- data/client/skr/screens/fresh-books-import/index.js +1 -0
- data/client/skr/screens/fresh-books-import/index.scss +39 -0
- data/client/skr/screens/gl-accounts/GlAccounts.cjsx +31 -0
- data/client/skr/screens/gl-accounts/index.js +5 -0
- data/client/skr/screens/gl-transactions/GlTransactions.cjsx +46 -0
- data/client/skr/screens/gl-transactions/index.js +1 -0
- data/client/skr/screens/gl-transactions/index.scss +12 -0
- data/client/skr/screens/invoice/Invoice.cjsx +92 -0
- data/client/skr/screens/invoice/Payment.cjsx +28 -0
- data/client/skr/screens/invoice/index.js +5 -0
- data/client/skr/screens/locations/Locations.cjsx +31 -0
- data/client/skr/screens/locations/index.js +5 -0
- data/client/skr/screens/payment-category/PaymentCategory.cjsx +28 -0
- data/client/skr/screens/payment-category/index.js +5 -0
- data/client/skr/screens/payment-category/index.scss +9 -0
- data/client/skr/screens/payment-terms/PaymentTerms.cjsx +28 -0
- data/client/skr/screens/payment-terms/index.js +5 -0
- data/client/skr/screens/payment-terms/index.scss +9 -0
- data/client/skr/screens/payments/Payments.cjsx +59 -0
- data/client/skr/screens/payments/index.js +5 -0
- data/client/skr/screens/sales-order/SalesOrder.cjsx +68 -0
- data/client/skr/screens/sales-order/index.js +1 -5
- data/client/skr/screens/sku-maint/SkuMaint.cjsx +53 -0
- data/client/skr/screens/sku-maint/SkuUomList.cjsx +209 -0
- data/client/skr/screens/sku-maint/index.js +2 -5
- data/client/skr/screens/sku-maint/index.scss +37 -6
- data/client/skr/screens/time-invoicing/TimeInvoicing.cjsx +156 -0
- data/client/skr/screens/time-invoicing/index.js +5 -0
- data/client/skr/screens/time-invoicing/index.scss +7 -0
- data/client/skr/screens/time-tracking/EditEntry.cjsx +54 -0
- data/client/skr/screens/time-tracking/Entries.coffee +132 -0
- data/client/skr/screens/time-tracking/Header.cjsx +71 -0
- data/client/skr/screens/time-tracking/Popover.cjsx +70 -0
- data/client/skr/screens/time-tracking/PopoverMiniControls.cjsx +25 -0
- data/client/skr/screens/time-tracking/TimeTracking.cjsx +63 -0
- data/client/skr/screens/time-tracking/WeekSummary.cjsx +16 -0
- data/client/skr/screens/time-tracking/index.js +1 -0
- data/client/skr/screens/time-tracking/index.scss +126 -0
- data/client/skr/screens/vendor-maint/VendorMaint.cjsx +45 -0
- data/client/skr/screens/vendor-maint/index.js +1 -5
- data/client/skr/styles.scss +1 -13
- data/config/puma.rb +4 -0
- data/config/routes.rb +21 -9
- data/config/screens.rb +147 -32
- data/db/migrate/20140202194700_create_skr_gl_transaction_details.rb +35 -0
- data/db/migrate/20140220031800_create_skr_locations.rb +2 -0
- data/db/migrate/20140220190836_create_skr_vendors.rb +1 -0
- data/db/migrate/20140220203029_create_skr_customers.rb +3 -2
- data/db/migrate/20140224034759_create_skr_skus.rb +2 -3
- data/db/migrate/20140322223912_create_skr_sales_orders.rb +4 -3
- data/db/migrate/20140322223920_create_skr_so_lines.rb +4 -5
- data/db/migrate/20140323001446_create_so_details_view.rb +7 -5
- data/db/migrate/20140327202209_create_skr_pt_lines.rb +2 -2
- data/db/migrate/20140327214000_create_customer_project.rb +16 -0
- data/db/migrate/20140327223002_create_time_entries.rb +17 -0
- data/db/migrate/20140327224000_create_skr_invoices.rb +5 -1
- data/db/migrate/20140327224002_create_skr_inv_lines.rb +3 -1
- data/db/migrate/20140422024010_create_skr_inv_details_view.rb +1 -1
- data/db/migrate/20151121211323_create_customer_project_details_views.rb +31 -0
- data/db/migrate/20160216142845_create_gl_account_balances_view.rb +20 -0
- data/db/migrate/20160229002044_create_bank_accounts.rb +18 -0
- data/db/migrate/20160229041711_create_payments.rb +33 -0
- data/db/migrate/20160307022705_create_create_combined_uom_views.rb +18 -0
- data/db/schema.sql +639 -140
- data/db/seed/chart_of_accounts.yml +8 -6
- data/db/seed/payment_categories.yml +12 -0
- data/db/seed/skus.yml +32 -0
- data/db/seed.rb +21 -0
- data/lib/skr/access_roles.rb +19 -6
- data/lib/skr/concerns/has_sku_loc_lines.rb +0 -16
- data/lib/skr/concerns/inv_extensions.rb +24 -0
- data/lib/skr/concerns/is_sku_loc_line.rb +3 -4
- data/lib/skr/concerns/so_extensions.rb +8 -0
- data/lib/skr/concerns/visible_id_identifier.rb +1 -1
- data/lib/skr/db/migration_helpers.rb +2 -4
- data/lib/skr/extension.rb +11 -4
- data/lib/skr/handlers/fresh_books_import.rb +20 -0
- data/lib/skr/handlers/invoice_from_time_entries.rb +49 -0
- data/lib/skr/jobs/fresh_books/base.rb +54 -0
- data/lib/skr/jobs/fresh_books/import.rb +151 -0
- data/lib/skr/jobs/fresh_books/retrieve.rb +62 -0
- data/lib/skr/model.rb +5 -0
- data/lib/skr/models/address.rb +1 -1
- data/lib/skr/models/bank_account.rb +13 -0
- data/lib/skr/models/business_entity.rb +3 -0
- data/lib/skr/models/customer.rb +1 -1
- data/lib/skr/models/customer_project.rb +22 -0
- data/lib/skr/models/gl_account.rb +13 -3
- data/lib/skr/models/gl_period.rb +6 -0
- data/lib/skr/models/gl_posting.rb +7 -4
- data/lib/skr/models/gl_transaction.rb +19 -33
- data/lib/skr/models/ia_line.rb +1 -1
- data/lib/skr/models/inv_line.rb +33 -15
- data/lib/skr/models/invoice.rb +47 -20
- data/lib/skr/models/location.rb +7 -1
- data/lib/skr/models/payment.rb +49 -0
- data/lib/skr/models/payment_category.rb +11 -0
- data/lib/skr/models/payment_term.rb +1 -1
- data/lib/skr/models/por_line.rb +1 -1
- data/lib/skr/models/pt_line.rb +1 -1
- data/lib/skr/models/sales_order.rb +9 -9
- data/lib/skr/models/sku_loc.rb +1 -1
- data/lib/skr/models/sku_tran.rb +6 -11
- data/lib/skr/models/so_line.rb +22 -12
- data/lib/skr/models/time_entry.rb +36 -0
- data/lib/skr/models/uom.rb +11 -10
- data/lib/skr/models/user_proxy.rb +1 -1
- data/lib/skr/number.rb +25 -0
- data/lib/skr/print/form.rb +46 -0
- data/lib/skr/print/template.rb +48 -0
- data/lib/skr/print.rb +11 -0
- data/lib/skr/string.rb +11 -0
- data/lib/skr/version.rb +1 -1
- data/lib/skr.rb +9 -0
- data/spec/fixtures/skr/address.yml +164 -4
- data/spec/fixtures/skr/bank_account.yml +8 -0
- data/spec/fixtures/skr/customer.yml +30 -4
- data/spec/fixtures/skr/customer_project.yml +20 -0
- data/spec/fixtures/skr/gl_account.yml +19 -1
- data/spec/fixtures/skr/gl_period.yml +3 -0
- data/spec/fixtures/skr/gl_posting.yml +22 -1
- data/spec/fixtures/skr/gl_transaction.yml +4 -1
- data/spec/fixtures/skr/inv_line.yml +35 -0
- data/spec/fixtures/skr/invoice.yml +13 -2
- data/spec/fixtures/skr/location.yml +5 -0
- data/spec/fixtures/skr/payment.yml +10 -0
- data/spec/fixtures/skr/payment_category.yml +8 -0
- data/spec/fixtures/skr/payment_term.yml +37 -3
- data/spec/fixtures/skr/sales_order.yml +12 -1
- data/spec/fixtures/skr/sku.yml +78 -1
- data/spec/fixtures/skr/sku_loc.yml +42 -1
- data/spec/fixtures/skr/sku_tran.yml +24 -1
- data/spec/fixtures/skr/so_line.yml +32 -0
- data/spec/fixtures/skr/time_entry.yml +82 -0
- data/spec/fixtures/skr/uom.yml +52 -1
- data/spec/fixtures/skr/vendor.yml +28 -1
- data/spec/fixtures/stockor.png +0 -0
- data/spec/server/bank_account_spec.rb +10 -0
- data/spec/server/customer_project_spec.rb +10 -0
- data/spec/server/handlers/invoice_from_time_entries_spec.rb +49 -0
- data/spec/server/jobs/fresh_books/import_spec.rb +69 -0
- data/spec/server/jobs/fresh_books/retrieve_spec.rb +37 -0
- data/spec/server/models/address_spec.rb +4 -3
- data/spec/server/models/gl_transaction_spec.rb +3 -3
- data/spec/server/models/inv_line_spec.rb +83 -3
- data/spec/server/models/invoice_spec.rb +32 -3
- data/spec/server/models/payment_spec.rb +40 -0
- data/spec/server/models/sales_order_spec.rb +1 -1
- data/spec/server/models/so_line_spec.rb +3 -3
- data/spec/server/models/spec_helper_spec.rb +1 -1
- data/spec/server/payment_spec.rb +10 -0
- data/spec/server/print/form_spec.rb +47 -0
- data/spec/server/print/template_spec.rb +36 -0
- data/spec/server/spec_helper.rb +14 -1
- data/spec/server/time_entry_spec.rb +10 -0
- data/spec/skr/components/SkuLinesSpec.coffee +61 -0
- data/spec/skr/models/BankAccountSpec.coffee +5 -0
- data/spec/skr/models/CustomerProjectSpec.coffee +5 -0
- data/spec/skr/models/CustomerSpec.coffee +2 -2
- data/spec/skr/models/PaymentSpec.coffee +5 -0
- data/spec/skr/models/SalesOrderSpec.coffee +21 -5
- data/spec/skr/models/SoLineSpec.coffee +7 -2
- data/spec/skr/models/TimeEntrySpec.coffee +5 -0
- data/spec/skr/screens/bank-maint/BankMaintSpec.coffee +5 -0
- data/spec/skr/screens/customer-projects/CustomerProjectsSpec.coffee +5 -0
- data/spec/skr/screens/fresh-books-import/FreshBooksImportSpec.coffee +1 -0
- data/spec/skr/screens/gl-accounts/GlAccountsSpec.coffee +5 -0
- data/spec/skr/screens/invoice/InvoiceSpec.coffee +5 -0
- data/spec/skr/screens/locations/LocationsSpec.coffee +5 -0
- data/spec/skr/screens/payment-category/PaymentCategorySpec.coffee +5 -0
- data/spec/skr/screens/payment-terms/PaymentTermsSpec.coffee +5 -0
- data/spec/skr/screens/payments/PaymentsSpec.coffee +5 -0
- data/spec/skr/screens/time-invoicing/TimeInvoicingSpec.coffee +5 -0
- data/spec/skr/screens/time-tracking/TimeTrackingSpec.coffee +14 -0
- data/spec/vcr/freshbooks.yml +698 -0
- data/stockor.gemspec +5 -1
- data/templates/print/fonts/GnuMICR.otf +0 -0
- data/templates/print/layout.tex.erb +39 -0
- data/templates/print/packages/booktabs.sty +182 -0
- data/templates/print/packages/fancybox.sty +966 -0
- data/templates/print/packages/fancyhdr.sty +485 -0
- data/templates/print/packages/graphbox.sty +129 -0
- data/templates/print/packages/lastpage.sty +283 -0
- data/templates/print/packages/lastpage209.sty +70 -0
- data/templates/print/packages/marginnote.sty +412 -0
- data/templates/print/packages/multirow.sty +159 -0
- data/templates/print/packages/rotating.sty +282 -0
- data/templates/print/packages/tabu.sty +2557 -0
- data/templates/print/packages/textpos.sty +361 -0
- data/templates/print/packages/varwidth.sty +318 -0
- data/templates/print/partials/address.tex.erb +6 -0
- data/templates/print/partials/bill_to_ship_to.tex.erb +13 -0
- data/templates/print/partials/header.tex.erb +13 -0
- data/templates/print/partials/invoice_paid_state.tex.erb +2 -0
- data/templates/print/partials/old/inv_lines_grouping.tex.erb +8 -0
- data/templates/print/partials/old/labor_lines_footer.tex.erb +18 -0
- data/templates/print/partials/skus_table.tex.erb +32 -0
- data/templates/print/partials/skus_table_col_hdr.tex.erb +8 -0
- data/templates/print/partials/skus_table_footer.tex.erb +5 -0
- data/templates/print/partials/skus_table_group_footer.tex.erb +4 -0
- data/templates/print/partials/skus_table_invoice_footer.tex.erb +25 -0
- data/templates/print/partials/skus_table_invoice_info_line.tex.erb +16 -0
- data/templates/print/partials/skus_table_labor_col_hdr.tex.erb +8 -0
- data/templates/print/partials/skus_table_labor_group_footer.tex.erb +7 -0
- data/templates/print/partials/skus_table_labor_line.tex.erb +11 -0
- data/templates/print/partials/skus_table_line.tex.erb +6 -0
- data/templates/print/partials/skus_table_other_charge_lines.tex.erb +7 -0
- data/templates/print/partials/so_info_line.tex.erb +14 -0
- data/templates/print/types/invoice/default.tex.erb +13 -0
- data/templates/print/types/invoice/labor.tex.erb +33 -0
- data/templates/print/types/payment/default.tex.erb +64 -0
- data/templates/print/types/sales-order/default.tex.erb +8 -0
- metadata +252 -15
- data/client/skr/components/address/address.html +0 -20
- data/client/skr/models/mixins/CodeField.coffee +0 -5
- data/client/skr/screens/customer-maint/index.scss +0 -11
- data/client/skr/screens/customer-maint/layout.html +0 -32
- data/client/skr/screens/sales-order/SalesOrder.coffee +0 -30
- data/client/skr/screens/sales-order/index.scss +0 -8
- data/client/skr/screens/sales-order/layout.html +0 -30
- data/client/skr/screens/sku-maint/SkuMaint.coffee +0 -18
- data/client/skr/screens/sku-maint/layout.html +0 -16
- data/client/skr/screens/vendor-maint/VendorMaint.coffee +0 -28
- data/client/skr/screens/vendor-maint/index.scss +0 -8
- 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>
|
@@ -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,8 +1,39 @@
|
|
1
|
-
|
2
|
-
If your screen does not use any custom styles
|
1
|
+
.sku-maint {
|
3
2
|
|
4
|
-
|
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
|
-
|
7
|
-
|
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,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>
|