stockor 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +15 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +97 -193
- data/client/skr/Extension.coffee +8 -4
- data/client/skr/api.js +21 -0
- data/client/skr/api.scss +148 -0
- data/client/skr/api/Components/AddressForm.cjsx +47 -0
- data/client/skr/api/Components/Base.coffee +7 -0
- data/client/skr/api/Components/SaleHistory.cjsx +32 -0
- data/client/skr/api/Components/SingleItemCart.cjsx +30 -0
- data/client/skr/api/Models/Base.coffee +10 -0
- data/client/skr/api/Models/Cart.coffee +40 -0
- data/client/skr/api/Models/Sale.coffee +43 -0
- data/client/skr/api/Models/SalesHistory.coffee +17 -0
- data/client/skr/api/Models/Sku.coffee +16 -0
- data/client/skr/api/SingleItemCheckout.cjsx +99 -0
- data/client/skr/api/namespace.js +6 -0
- data/client/skr/api/onReady.coffee +23 -0
- data/client/skr/components/CreditCardForm.cjsx +35 -0
- data/client/skr/components/CustomerFinder.cjsx +0 -3
- data/client/skr/components/InvoiceFinder.cjsx +1 -0
- data/client/skr/components/LatexSnippets.cjsx +65 -0
- data/client/skr/components/LocationChooser.cjsx +5 -1
- data/client/skr/components/PrintButton.cjsx +33 -0
- data/client/skr/components/PrintFormChooser.cjsx +10 -10
- data/client/skr/components/SalesOrderFinder.cjsx +2 -1
- data/client/skr/components/SystemSettings.cjsx +69 -9
- data/client/skr/components/address/index.js +1 -0
- data/client/skr/models/Address.coffee +3 -0
- data/client/skr/models/CreditCard.coffee +49 -0
- data/client/skr/models/CreditCardGateway.coffee +27 -0
- data/client/skr/models/Invoice.coffee +13 -5
- data/client/skr/models/Location.coffee +6 -4
- data/client/skr/models/Payment.coffee +33 -13
- data/client/skr/models/SalesOrder.coffee +7 -3
- data/client/skr/models/SequentialId.coffee +17 -0
- data/client/skr/models/Sku.coffee +1 -1
- data/client/skr/models/TimeEntry.coffee +3 -4
- data/client/skr/models/mixins/PrintSupport.coffee +4 -1
- data/client/skr/models/mixins/SkuLine.coffee +1 -1
- data/client/skr/screens/customer-maint/CustomerMaint.cjsx +1 -2
- data/client/skr/screens/customer-projects/CustomerProjects.cjsx +7 -3
- data/client/skr/screens/customer-projects/index.scss +1 -0
- data/client/skr/screens/fresh-books-import/ApiInfo.cjsx +1 -1
- 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 +9 -17
- data/client/skr/screens/invoice/Payment.cjsx +94 -13
- data/client/skr/screens/invoice/index.scss +32 -0
- data/client/skr/screens/locations/Locations.cjsx +3 -2
- data/client/skr/screens/payment-category/PaymentCategory.cjsx +1 -1
- data/client/skr/screens/payments/Payments.cjsx +5 -4
- data/client/skr/screens/sale-report/SaleReport.cjsx +73 -0
- data/client/skr/screens/sale-report/index.js +5 -0
- data/client/skr/screens/sale-report/index.scss +9 -0
- data/client/skr/screens/sales-order/SalesOrder.cjsx +4 -4
- data/client/skr/screens/sku-maint/SkuMaint.cjsx +5 -0
- data/client/skr/screens/sku-maint/SkuUomList.cjsx +45 -56
- data/client/skr/screens/sku-maint/index.scss +33 -13
- data/client/skr/screens/time-invoicing/TimeInvoicing.cjsx +2 -2
- data/client/skr/screens/time-tracking/EditEntry.cjsx +2 -4
- data/client/skr/screens/time-tracking/TimeTracking.cjsx +1 -1
- data/client/skr/screens/vendor-maint/VendorMaint.cjsx +1 -1
- data/client/skr/vendor/index.js +2438 -0
- data/config/lanes.rb +10 -3
- data/config/routes.rb +9 -7
- data/config/screens.rb +39 -13
- data/db/migrate/20160517032350_create_remove_location_logos.rb +11 -0
- data/db/migrate/20160531014306_create_public_skus.rb +7 -0
- data/db/migrate/20160604195848_create_null_addresses.rb +9 -0
- data/db/migrate/20160605024432_create_sku_associations_views.rb +48 -0
- data/db/migrate/20160608023553_create_invoice_payments.rb +9 -0
- data/db/migrate/20160620010455_add_payments_to_inv_details.rb +54 -0
- data/db/schema.sql +206 -38
- data/db/seed.rb +6 -0
- data/lib/skr.rb +1 -1
- data/lib/skr/access_roles.rb +6 -1
- data/lib/skr/concerns/has_gl_transaction.rb +8 -0
- data/lib/skr/concerns/inv_extensions.rb +11 -0
- data/lib/skr/concerns/is_order_like.rb +3 -3
- data/lib/skr/concerns/visible_id_identifier.rb +3 -8
- data/lib/skr/configuration.rb +2 -0
- data/lib/skr/extension.rb +6 -0
- data/lib/skr/handlers/credit_card_gateway.rb +31 -0
- data/lib/skr/handlers/invoice_from_time_entries.rb +12 -26
- data/lib/skr/handlers/sales.rb +44 -0
- data/lib/skr/handlers/sequential_ids.rb +46 -0
- data/lib/skr/handlers/skus.rb +36 -0
- data/lib/skr/jobs/fresh_books/import.rb +3 -1
- data/lib/skr/merchant_gateway.rb +37 -0
- data/lib/skr/models/address.rb +7 -5
- data/lib/skr/models/bank_account.rb +12 -0
- data/lib/skr/models/business_entity.rb +1 -1
- data/lib/skr/models/gl_transaction.rb +3 -0
- data/lib/skr/models/inv_line.rb +7 -2
- data/lib/skr/models/inventory_adjustment.rb +0 -5
- data/lib/skr/models/invoice.rb +25 -36
- data/lib/skr/models/location.rb +1 -1
- data/lib/skr/models/payment.rb +56 -10
- data/lib/skr/models/po_receipt.rb +0 -8
- data/lib/skr/models/sales_order.rb +7 -2
- data/lib/skr/models/sequential_id.rb +6 -1
- data/lib/skr/models/sku.rb +3 -0
- data/lib/skr/print.rb +1 -0
- data/lib/skr/print/context.rb +19 -0
- data/lib/skr/print/form.rb +7 -1
- data/lib/skr/version.rb +1 -1
- data/npm-build/package.json +26 -0
- data/npm-build/vendor.js +10 -0
- data/npm-build/webpack.config.js +25 -0
- data/spec/fixtures/skr/bank_account.yml +9 -0
- data/spec/fixtures/skr/customer.yml +10 -0
- data/spec/fixtures/skr/inv_line.yml +12 -0
- data/spec/fixtures/skr/invoice.yml +17 -0
- data/spec/fixtures/skr/payment_category.yml +6 -0
- data/spec/fixtures/skr/sales_order.yml +1 -1
- data/spec/fixtures/skr/sku.yml +10 -0
- data/spec/fixtures/skr/sku_loc.yml +4 -0
- data/spec/fixtures/skr/uom.yml +6 -0
- data/spec/server/handlers/invoice_from_time_entries_spec.rb +13 -6
- data/spec/server/handlers/sequential_ids_spec.rb +22 -0
- data/spec/server/models/invoice_spec.rb +36 -0
- data/spec/server/models/payment_spec.rb +50 -22
- data/spec/server/models/sales_order_spec.rb +12 -0
- data/spec/server/print/form_spec.rb +20 -4
- data/spec/skr/api/SingleItemCheckoutSpec.cjsx +10 -0
- data/spec/skr/screens/sale-report/SaleReportSpec.coffee +5 -0
- data/stockor.gemspec +5 -4
- data/templates/print/layout.tex.erb +1 -1
- data/templates/print/packages/INSTALL +7 -0
- data/templates/print/packages/qrcode.sty +3051 -0
- data/templates/print/packages/svgnam.def +186 -0
- data/templates/print/packages/x11nam.def +352 -0
- data/templates/print/packages/xcolor.pro +58 -0
- data/templates/print/packages/xcolor.sty +1460 -0
- data/templates/print/types/invoice/default.tex.erb +2 -0
- data/templates/print/types/invoice/labor.tex.erb +2 -1
- data/templates/print/types/invoice/ticket.tex.erb +41 -0
- data/templates/print/types/payment/default.tex.erb +13 -12
- metadata +78 -12
data/client/skr/Extension.coffee
CHANGED
@@ -23,10 +23,14 @@ class Skr.Extension extends Lanes.Extensions.Base
|
|
23
23
|
else
|
24
24
|
console.log "Unable to find model for #{type}"
|
25
25
|
|
26
|
+
title: ->
|
27
|
+
"Stockor"
|
28
|
+
|
26
29
|
rootComponent: (viewport) ->
|
27
30
|
Lanes.Workspace.Layout
|
28
31
|
|
29
|
-
|
30
|
-
React.createElement(SC.UserPreferences,
|
31
|
-
|
32
|
-
|
32
|
+
getPreferenceElement: (props) ->
|
33
|
+
React.createElement(SC.UserPreferences, props)
|
34
|
+
|
35
|
+
getSettingsElement: (props) ->
|
36
|
+
React.createElement(SC.SystemSettings, props)
|
data/client/skr/api.js
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
//=require lanes/remote/api
|
2
|
+
//=require ./api/namespace
|
3
|
+
//=require skr/vendor
|
4
|
+
//=require ./api/Models/Base
|
5
|
+
//=require_tree ./models/mixins
|
6
|
+
//=require ../api/Components/Base
|
7
|
+
//=require ./api/Components/Base
|
8
|
+
//=require_tree ./api
|
9
|
+
//=require_self
|
10
|
+
|
11
|
+
|
12
|
+
var previousSkr = window.Skr;
|
13
|
+
window.Skr = Lanes.Skr;
|
14
|
+
|
15
|
+
window.Skr._lanes = window.Lanes.noConflict();
|
16
|
+
|
17
|
+
Skr.noConflict = function(){
|
18
|
+
var Skr = window.Skr;
|
19
|
+
window.Skr = previousSkr;
|
20
|
+
return Skr;
|
21
|
+
};
|
data/client/skr/api.scss
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
.skr-simple-checkout {
|
2
|
+
width: 100%;
|
3
|
+
max-width: 350px;
|
4
|
+
margin: 50px auto;
|
5
|
+
.section {
|
6
|
+
margin-top: 2rem;
|
7
|
+
padding-top: 2rem;
|
8
|
+
border-top: 2px solid grey;
|
9
|
+
}
|
10
|
+
form { }
|
11
|
+
|
12
|
+
input {
|
13
|
+
font-size: 18px;
|
14
|
+
padding: 5px;
|
15
|
+
}
|
16
|
+
.errors {
|
17
|
+
color: #D8000C;
|
18
|
+
background-color: #FFBABA;
|
19
|
+
border: 1px solid darken(#FFBABA, 50%);
|
20
|
+
}
|
21
|
+
.address {
|
22
|
+
label {
|
23
|
+
display: flex;
|
24
|
+
justify-content: flex-end;
|
25
|
+
span { margin-right: 1rem; }
|
26
|
+
input { width: 200px; }
|
27
|
+
}
|
28
|
+
}
|
29
|
+
.cart {
|
30
|
+
width: 100%;
|
31
|
+
td, th {
|
32
|
+
&:last-child { text-align: right; }
|
33
|
+
}
|
34
|
+
input {
|
35
|
+
width: 4rem;
|
36
|
+
text-align: center;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
.credit-card {
|
40
|
+
.row {
|
41
|
+
display: flex;
|
42
|
+
align-items: stretch;
|
43
|
+
height: 30px;
|
44
|
+
margin: 10px auto;
|
45
|
+
}
|
46
|
+
input {
|
47
|
+
flex: 1;
|
48
|
+
width: 100%;
|
49
|
+
&[name='expiry'], &[name='cvc'] {
|
50
|
+
flex: 0.5;
|
51
|
+
}
|
52
|
+
&.jp-card-invalid {
|
53
|
+
border: 1px solid red;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
button {
|
58
|
+
border: 0;
|
59
|
+
background: #3498db;
|
60
|
+
background-image: -webkit-linear-gradient(top, #3498db, #2980b9);
|
61
|
+
background-image: -moz-linear-gradient(top, #3498db, #2980b9);
|
62
|
+
background-image: -ms-linear-gradient(top, #3498db, #2980b9);
|
63
|
+
background-image: -o-linear-gradient(top, #3498db, #2980b9);
|
64
|
+
background-image: linear-gradient(to bottom, #3498db, #2980b9);
|
65
|
+
font-family: Arial;
|
66
|
+
color: #f0edf0;
|
67
|
+
font-size: 22px;
|
68
|
+
padding: 10px 20px 10px 20px;
|
69
|
+
text-decoration: none;
|
70
|
+
&:hover {
|
71
|
+
background: #3cb0fd;
|
72
|
+
background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db);
|
73
|
+
background-image: -moz-linear-gradient(top, #3cb0fd, #3498db);
|
74
|
+
background-image: -ms-linear-gradient(top, #3cb0fd, #3498db);
|
75
|
+
background-image: -o-linear-gradient(top, #3cb0fd, #3498db);
|
76
|
+
background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
|
77
|
+
text-decoration: none;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
@mixin spinner($opacity, $size){
|
81
|
+
box-shadow: rgba(0, 0, 0, $opacity) $size*1.5 0 0 0,
|
82
|
+
rgba(0, 0, 0, $opacity) ($size*1.1) ($size*1.1) 0 0,
|
83
|
+
rgba(0, 0, 0, $opacity) 0 ($size*1.5) 0 0,
|
84
|
+
rgba(0, 0, 0, $opacity) (-$size*1.1) ($size*1.1) 0 0,
|
85
|
+
rgba(0, 0, 0, $opacity) (-$size*1.5) 0 0 0,
|
86
|
+
rgba(0, 0, 0, $opacity) (-$size*1.1) (-$size*1.1) 0 0,
|
87
|
+
rgba(0, 0, 0, $opacity) 0 (-$size*1.5) 0 0,
|
88
|
+
rgba(0, 0, 0, $opacity) $size*1.1 (-$size*1.1) 0 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
$spinner-size: 10px;
|
92
|
+
.mask {
|
93
|
+
background-color: transparent;
|
94
|
+
display: none;
|
95
|
+
}
|
96
|
+
.order {
|
97
|
+
&.is-saving {
|
98
|
+
position: relative;
|
99
|
+
.mask {
|
100
|
+
position: absolute;
|
101
|
+
display: flex;
|
102
|
+
justify-content: center;
|
103
|
+
align-items: center;
|
104
|
+
top: 0;
|
105
|
+
left: 0;
|
106
|
+
bottom: 0;
|
107
|
+
right: 0;
|
108
|
+
font-size: 2.8rem;
|
109
|
+
text-shadow: none;
|
110
|
+
border: 0;
|
111
|
+
transition: all 0.8s ease-in-out;
|
112
|
+
background-color: rgba(221, 221, 221, 0.7);
|
113
|
+
z-index: 2;
|
114
|
+
.msg {
|
115
|
+
transition: all 1s ease-in-out;
|
116
|
+
color: rgba(0, 0, 0, 0.8);
|
117
|
+
span { margin-left: $spinner-size*4; }
|
118
|
+
i {
|
119
|
+
transition: all 1s ease-in-out;
|
120
|
+
display: block;
|
121
|
+
position: relative;
|
122
|
+
width: $spinner-size;
|
123
|
+
height: $spinner-size;
|
124
|
+
top: $spinner-size*4;
|
125
|
+
left: $spinner-size*1.5;
|
126
|
+
animation: spinner 3000ms infinite linear;
|
127
|
+
border-radius: $spinner-size / 2;
|
128
|
+
@include spinner(0.75, $spinner-size);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
&.is-complete {
|
133
|
+
.mask {
|
134
|
+
background-color: rgba(221, 221, 221, 0);
|
135
|
+
.msg {
|
136
|
+
color: rgba(0, 0, 0, 0);
|
137
|
+
i { @include spinner(0.0, $spinner-size); }
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
}
|
142
|
+
@keyframes spinner {
|
143
|
+
0% { transform: rotate(0deg); }
|
144
|
+
100% { transform: rotate(360deg); }
|
145
|
+
}
|
146
|
+
|
147
|
+
}
|
148
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Skr.Api.Components.AddressForm extends Skr.Api.Components.Base
|
2
|
+
|
3
|
+
dataObjects:
|
4
|
+
address: 'props'
|
5
|
+
|
6
|
+
setField: (ev) ->
|
7
|
+
@address[ev.target.name] = ev.target.value
|
8
|
+
|
9
|
+
render: ->
|
10
|
+
fieldProps =
|
11
|
+
onChange: @setField
|
12
|
+
type: 'text'
|
13
|
+
|
14
|
+
<div className="address">
|
15
|
+
<label>
|
16
|
+
<span>Name:</span>
|
17
|
+
<input {...fieldProps} name="name" />
|
18
|
+
</label>
|
19
|
+
<label>
|
20
|
+
<span>Email:</span>
|
21
|
+
<input {...fieldProps} name="email" />
|
22
|
+
</label>
|
23
|
+
<label>
|
24
|
+
<span>Phone:</span>
|
25
|
+
<input {...fieldProps} name="phone" />
|
26
|
+
</label>
|
27
|
+
<label>
|
28
|
+
<span>Address line 1:</span>
|
29
|
+
<input {...fieldProps} name="line1" />
|
30
|
+
</label>
|
31
|
+
<label>
|
32
|
+
<span>Address line 2:</span>
|
33
|
+
<input {...fieldProps} name="line2" />
|
34
|
+
</label>
|
35
|
+
<label>
|
36
|
+
<span>City:</span>
|
37
|
+
<input {...fieldProps} name="city" />
|
38
|
+
</label>
|
39
|
+
<label>
|
40
|
+
<span>State:</span>
|
41
|
+
<input {...fieldProps} name="state" />
|
42
|
+
</label>
|
43
|
+
<label>
|
44
|
+
<span>Postal Code:</span>
|
45
|
+
<input {...fieldProps} name="postal_code" />
|
46
|
+
</label>
|
47
|
+
</div>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Skr.Api.Components.SaleHistory extends Skr.Api.Components.Base
|
2
|
+
|
3
|
+
componentWillMount: ->
|
4
|
+
@setState(orders: Skr.Api.Models.SalesHistory.get())
|
5
|
+
|
6
|
+
render: ->
|
7
|
+
return null if _.isEmpty( @state.orders )
|
8
|
+
|
9
|
+
<table className="cart">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th colSpan=3>Previous Purchases</th>
|
13
|
+
</tr>
|
14
|
+
<tr>
|
15
|
+
<th>Sale Number</th>
|
16
|
+
<th>Date</th>
|
17
|
+
<th>Amount</th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
{for order in @state.orders
|
22
|
+
<tr>
|
23
|
+
<td>
|
24
|
+
<a target="_blank" href={order.pdfDownloadUrl()}>
|
25
|
+
{order.visible_id}
|
26
|
+
</a>
|
27
|
+
</td>
|
28
|
+
<td>{Lanes.u.format.shortDate(order.date)}</td>
|
29
|
+
<td>{Lanes.u.format.currency(order.total)}</td>
|
30
|
+
</tr>}
|
31
|
+
</tbody>
|
32
|
+
</table>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Skr.Api.Components.SingleItemCart extends Skr.Api.Components.Base
|
2
|
+
|
3
|
+
dataObjects:
|
4
|
+
cart: 'props'
|
5
|
+
|
6
|
+
item: -> @cart.skus.first()
|
7
|
+
|
8
|
+
setQty: (ev) ->
|
9
|
+
@item().qty = ev.target.value
|
10
|
+
|
11
|
+
render: ->
|
12
|
+
item = @item()
|
13
|
+
return null unless item
|
14
|
+
|
15
|
+
<table className="cart">
|
16
|
+
<tbody>
|
17
|
+
<tr>
|
18
|
+
<td colSpan="4">{item.sku.description}</td>
|
19
|
+
<td>{item.sku.display_price}</td>
|
20
|
+
</tr>
|
21
|
+
<tr>
|
22
|
+
<th>Qty:</th>
|
23
|
+
<td>
|
24
|
+
<input type="number" value={item.qty} onChange={@setQty} />
|
25
|
+
</td>
|
26
|
+
<th>Total:</th>
|
27
|
+
<th colSpan="2">{item.display_total}</th>
|
28
|
+
</tr>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class CartSku extends Lanes.Models.State
|
2
|
+
|
3
|
+
session:
|
4
|
+
sku: 'state'
|
5
|
+
qty: type: 'integer', default: 0, required: true
|
6
|
+
|
7
|
+
derived:
|
8
|
+
total: deps: ['qty', 'sku.price'], fn: ->
|
9
|
+
@sku.price.times(@qty)
|
10
|
+
display_total:
|
11
|
+
deps: ['total'], fn: ->
|
12
|
+
Lanes.u.format.currency @total
|
13
|
+
|
14
|
+
class Skr.Api.Models.Cart extends Skr.Api.Models.Base
|
15
|
+
|
16
|
+
session:
|
17
|
+
total:
|
18
|
+
type: 'bigdec', required: true, default: -> _.bigDecimal('0')
|
19
|
+
|
20
|
+
derived:
|
21
|
+
display_total:
|
22
|
+
deps: ['total'], fn: ->
|
23
|
+
Lanes.u.format.currency @total
|
24
|
+
|
25
|
+
associations:
|
26
|
+
skus: { collection: CartSku }
|
27
|
+
|
28
|
+
addSku: (sku, qty = 1) ->
|
29
|
+
ci = new CartSku({sku, qty})
|
30
|
+
@skus.add(ci)
|
31
|
+
|
32
|
+
initialize: ->
|
33
|
+
@listenToAndRun(@skus, 'add change', @onSkusChange)
|
34
|
+
|
35
|
+
onSkusChange: ->
|
36
|
+
@total = _.sumBy(@skus.models, 'total') unless @skus.isEmpty()
|
37
|
+
|
38
|
+
addBySkuCode: (code) ->
|
39
|
+
Skr.Api.Models.Sku.findByCode(code).then (sku) =>
|
40
|
+
@addSku(sku) unless sku.isNew()
|
@@ -0,0 +1,43 @@
|
|
1
|
+
##= require 'skr/models/Address'
|
2
|
+
##= require 'skr/models/CreditCard'
|
3
|
+
|
4
|
+
class SaleSku extends Lanes.Models.State
|
5
|
+
|
6
|
+
props:
|
7
|
+
sku_id: 'integer'
|
8
|
+
qty: 'integer'
|
9
|
+
|
10
|
+
|
11
|
+
class Skr.Api.Models.Sale extends Skr.Api.Models.Base
|
12
|
+
|
13
|
+
|
14
|
+
props:
|
15
|
+
address_id: 'integer'
|
16
|
+
id: 'integer'
|
17
|
+
visible_id: 'visible_id'
|
18
|
+
terms_id: 'integer'
|
19
|
+
customer_id: 'integer'
|
20
|
+
hash_code: 'string'
|
21
|
+
total: 'bigdec'
|
22
|
+
form: 'string'
|
23
|
+
options: 'object'
|
24
|
+
|
25
|
+
mixins: [ Lanes.Skr.Models.Mixins.PrintSupport ]
|
26
|
+
|
27
|
+
associations:
|
28
|
+
skus: { collection: SaleSku }
|
29
|
+
billing_address: { model: 'Address', autoCreate: true }
|
30
|
+
credit_card:
|
31
|
+
model: 'Skr.Models.CreditCard', autoCreate: true
|
32
|
+
options: ->
|
33
|
+
linkToAddress: @billing_address
|
34
|
+
|
35
|
+
printFormIdentifier: ->
|
36
|
+
'invoice'
|
37
|
+
|
38
|
+
copySkusFromCart: (cart) ->
|
39
|
+
cart.skus.each (ci) =>
|
40
|
+
@skus.add(sku_id: ci.sku.id, qty: ci.qty)
|
41
|
+
|
42
|
+
save: ->
|
43
|
+
super(with: 'details')
|
@@ -0,0 +1,17 @@
|
|
1
|
+
KEY = 'SALES-HISTORY'
|
2
|
+
|
3
|
+
Skr.Api.Models.SalesHistory = {
|
4
|
+
|
5
|
+
_encode: (sale) ->
|
6
|
+
_.pick(sale, 'visible_id', 'hash_code', 'invoice_date', 'total')
|
7
|
+
|
8
|
+
record: (sale) ->
|
9
|
+
sales = @get()
|
10
|
+
sales.push(@_encode(sale))
|
11
|
+
localStorage.setItem(KEY, JSON.stringify({sales}) )
|
12
|
+
|
13
|
+
get: ->
|
14
|
+
sales = JSON.parse(localStorage.getItem(KEY))?.sales
|
15
|
+
_.map sales, (sale) -> new Skr.Api.Models.Sale(sale)
|
16
|
+
|
17
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Skr.Api.Models.Sku extends Skr.Api.Models.Base
|
2
|
+
|
3
|
+
props:
|
4
|
+
id: {type:"integer"}
|
5
|
+
code: {type:"code" }
|
6
|
+
description: {type:"string" }
|
7
|
+
price: {type:"bigdec" }
|
8
|
+
default_uom_code: {type:"string" }
|
9
|
+
|
10
|
+
derived:
|
11
|
+
display_price: deps: ['price'], fn: ->
|
12
|
+
Lanes.u.format.currency @price
|
13
|
+
|
14
|
+
@findByCode: (code) ->
|
15
|
+
sku = new Skr.Api.Models.Sku({code})
|
16
|
+
sku.fetch(query: {code})
|