431 Commits
0.0.5 ... 0.0.7

Author SHA1 Message Date
bee48c4f0f Version Bump 0.0.7! 2016-07-28 20:37:13 -04:00
0f8fbfb8df Update qbo.rb 2016-07-28 20:34:31 -04:00
d71e9a78a1 Update qbo_controller.rb 2016-07-28 20:06:06 -04:00
7ac778586c Update qbo.rb 2016-07-28 20:03:36 -04:00
2558cb69b1 Update qbo_controller.rb 2016-07-28 19:52:42 -04:00
55ac8d12a5 Update qbo_controller.rb 2016-07-28 19:51:48 -04:00
a5dc5ce921 Update qbo.rb 2016-07-28 19:42:09 -04:00
de65cc0926 Update qbo.rb 2016-07-28 19:41:02 -04:00
80d3eed224 Update qbo_controller.rb 2016-07-28 19:32:24 -04:00
76beccfb9f Update qbo_controller.rb 2016-07-28 19:31:24 -04:00
5579cd9255 Update _settings.html.erb 2016-07-28 19:27:00 -04:00
236e84f11a Update _settings.html.erb 2016-07-28 19:23:20 -04:00
ed61dc6bbf Update qbo_controller.rb 2016-07-28 19:21:40 -04:00
2b7ac05338 Update qbo.rb 2016-07-28 19:19:13 -04:00
36e63995aa Update qbo_controller.rb 2016-07-28 19:15:19 -04:00
58d16fbc7d Update qbo_controller.rb 2016-07-28 19:12:36 -04:00
aa78482c36 Update qbo_controller.rb 2016-07-28 19:11:09 -04:00
c35b6a3f6b Update qbo_controller.rb 2016-07-28 18:35:44 -04:00
8d52c46a53 Update qbo_controller.rb 2016-07-28 18:31:54 -04:00
325f124e4e Update qbo_controller.rb 2016-07-28 18:30:48 -04:00
18d71a69f8 Update qbo_controller.rb 2016-07-28 18:27:00 -04:00
7d5fd72297 Update qbo_controller.rb 2016-07-28 18:21:58 -04:00
a625f6d9fc Update qbo_controller.rb 2016-07-28 18:17:44 -04:00
ede89cc6cf Update qbo_controller.rb 2016-07-28 18:15:56 -04:00
c60f06e8ed Webhook 2016-07-28 09:18:50 -04:00
863a5efa38 Webhook 2016-07-28 09:17:21 -04:00
670b0aac67 Webhook 2016-07-28 09:16:13 -04:00
d261b156bd Webhook 2016-07-28 09:14:18 -04:00
c49bdb731a Webhook 2016-07-28 09:13:16 -04:00
dc2993bdea Webhook 2016-07-28 09:09:38 -04:00
09e1c0ad48 Webhook 2016-07-28 09:07:51 -04:00
370153bed9 Webhook 2016-07-28 09:04:17 -04:00
b115c4bf67 Webhook 2016-07-28 09:03:55 -04:00
90a7ac1267 Webhook 2016-07-28 09:02:29 -04:00
887d330ba9 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2016-07-28 09:02:04 -04:00
fe97a589d9 Update 2016-07-28 09:01:41 -04:00
37d0b2321f Webhook 2016-07-28 08:59:43 -04:00
47aa454895 Webhook 2016-07-28 08:57:28 -04:00
fecc4956b4 Webhook 2016-07-28 08:52:30 -04:00
0d5fb8d3e3 Update qbo_controller.rb 2016-07-28 08:47:39 -04:00
ca6e51911b Webhook 2016-07-28 08:41:23 -04:00
8159487631 Webhook 2016-07-28 08:33:26 -04:00
392b27563a Webhooks 2016-07-28 07:55:20 -04:00
60dced41db Webhook 2016-07-28 01:07:54 -04:00
8b02a80904 Webhooks 2016-07-28 01:04:00 -04:00
ff977cc364 Update pdf_patch.rb 2016-07-22 19:01:43 -04:00
3578908832 Update pdf_patch.rb 2016-07-22 19:00:24 -04:00
4fcde967f1 Update issues_show_hook_listener.rb 2016-07-22 19:00:03 -04:00
4e81c16617 Update pdf_patch.rb 2016-07-22 16:02:57 -04:00
8149f5ab9b Update issues_show_hook_listener.rb 2016-07-22 15:59:49 -04:00
7800e52299 Update users_show_hook_listener.rb 2016-07-13 16:33:04 -04:00
c6f8fd7561 Update issues_form_hook_listener.rb 2016-06-04 10:09:27 -04:00
e3d26cea23 Update issue_patch.rb 2016-06-02 09:47:42 -04:00
4fd35d4cb6 Update issues_form_hook_listener.rb 2016-06-02 09:45:54 -04:00
cf00331497 Update issues_form_hook_listener.rb 2016-06-02 09:45:28 -04:00
dc8ea82b61 Update issues_form_hook_listener.rb 2016-06-02 09:41:54 -04:00
aab99e3abe Update issues_form_hook_listener.rb 2016-06-02 09:41:14 -04:00
f240a5a6a4 Update issues_form_hook_listener.rb 2016-06-02 09:40:13 -04:00
05ce348d8a Update issues_form_hook_listener.rb 2016-06-02 09:36:34 -04:00
67afbff93d Update issues_form_hook_listener.rb 2016-06-02 09:35:41 -04:00
bd92ca8f2c Fixed Vehicle Drop down 2016-06-02 09:25:52 -04:00
7ef3e31465 New Issue Button 2016-06-02 09:20:44 -04:00
f59aa18be8 Fixed Formatting 2016-06-02 09:02:06 -04:00
2699b37e4f Edmunds API Key 2016-06-02 08:56:13 -04:00
22f8138422 Edmunds API Key Setting 2016-06-02 08:54:37 -04:00
0727257d72 Update issues_save_hook_listener.rb 2016-06-01 12:01:51 -04:00
f8a9ffbe15 Setter for email 2016-05-31 11:16:41 -04:00
aac442ab55 Version Bump 0.0.6 2016-05-31 10:04:30 -04:00
b7f0bf6049 Update README.md 2016-05-31 10:03:42 -04:00
b7b9177edf Removed unneeded gems 2016-05-31 10:01:29 -04:00
f5d7e00ec6 Added Customer Name 2016-05-31 09:57:57 -04:00
4f8c57032c nil check for customer & moved notes to the right 2016-05-31 09:55:48 -04:00
96fcb81d9e Removed Customer Name from to_s 2016-05-31 09:47:39 -04:00
1b5663fa99 Update _list.html.erb 2016-05-31 09:41:40 -04:00
a2588040ff Update _details.html.erb 2016-05-31 09:40:59 -04:00
947f56899d Fixed typo 2016-05-31 09:39:16 -04:00
731e709174 Update customer.rb 2016-05-31 08:50:56 -04:00
c3cce531d6 Update customer.rb 2016-05-31 08:48:31 -04:00
ca63852b4f Update customer.rb 2016-05-31 08:47:11 -04:00
9342ef146c Update vehicle.rb 2016-05-31 08:21:05 -04:00
00b6939571 Update vehicles_controller.rb 2016-05-31 08:20:26 -04:00
0376233ace Update vehicles_controller.rb 2016-05-31 08:18:04 -04:00
70533ae3c3 Update _form.html.erb 2016-05-31 08:09:35 -04:00
d7613bd5ba Update _form.html.erb 2016-05-31 08:07:45 -04:00
06bd0dfcce Update vehicle.rb 2016-05-31 08:06:02 -04:00
78708733be Update vehicle.rb 2016-05-31 07:58:02 -04:00
e7ae654066 Update vehicle.rb 2016-05-31 07:53:29 -04:00
5c0c0cc657 Update vehicle.rb 2016-05-31 07:52:37 -04:00
9d043e4bc8 Update customer.rb 2016-05-31 07:47:18 -04:00
08b539dc1e Comments & Sync 2016-05-31 07:42:41 -04:00
e5147b3893 Update customer.rb 2016-05-31 07:23:13 -04:00
01a2b2a1b1 Update customer.rb 2016-05-31 07:21:05 -04:00
e89f2d17e7 Update customer.rb 2016-05-31 06:55:32 -04:00
7e0888d375 Update customer.rb 2016-05-31 06:54:11 -04:00
f435f7f3c8 Update customer.rb 2016-05-31 06:49:15 -04:00
0d2be843f5 Update customer.rb 2016-05-31 06:37:11 -04:00
6e7ec44188 More progress 2016-05-30 09:30:33 -04:00
ba152e69d2 Update query_patch.rb 2016-05-29 11:54:49 -04:00
42212a073c Update query_patch.rb 2016-05-29 11:54:08 -04:00
469f8c739c Update query_patch.rb 2016-05-29 11:50:27 -04:00
53505857d6 Update query_patch.rb 2016-05-29 11:49:54 -04:00
89a02d85fe Update query_patch.rb 2016-05-29 11:47:34 -04:00
6249b057af Update query_patch.rb 2016-05-29 11:45:46 -04:00
f760ee057d Update query_patch.rb 2016-05-29 11:44:33 -04:00
291bff0813 Update query_patch.rb 2016-05-29 11:43:35 -04:00
79edbed9ce Update query_patch.rb 2016-05-29 11:37:45 -04:00
54c797c114 Update query_patch.rb 2016-05-29 11:31:25 -04:00
201a577588 Update qbo_item.rb 2016-05-29 11:18:43 -04:00
4dfbdbfdda Update customer.rb 2016-05-29 11:17:38 -04:00
3e5008aeb2 Update qbo_invoice.rb 2016-05-29 11:16:33 -04:00
bfb6d3bc4e Removed after init call back from customer 2016-05-29 11:14:26 -04:00
d829c2f83a Fixed various issues 2016-05-29 10:30:09 -04:00
ec1063f80f Update qbo_controller.rb 2016-05-25 10:49:38 -04:00
3b20c29d0a Update Gemfile 2016-05-25 10:47:22 -04:00
f2dc4b03ef Delete vehicle_helper.rb 2016-05-25 10:46:40 -04:00
22e4aba1cf Delete qbo_helper.rb 2016-05-25 10:46:34 -04:00
ece22c73ae Delete invoice_helper.rb 2016-05-25 10:46:26 -04:00
ed7e5d04ec Delete estimate_helper.rb 2016-05-25 10:46:21 -04:00
6a595ab30c Delete CustomerBackgroundHelper.rb 2016-05-25 10:46:14 -04:00
821606ee5e Delete BaseBackgroundHelper.rb 2016-05-25 10:46:08 -04:00
61440a2aca Create CustomerBackgroundHelper.rb 2016-05-25 10:28:46 -04:00
01eefe0a04 Update BaseBackgroundHelper.rb 2016-05-25 10:25:26 -04:00
9057ef3edb Update BaseBackgroundHelper.rb 2016-05-25 10:25:01 -04:00
4f333c9b94 Update BaseBackgroundHelper.rb 2016-05-25 10:24:08 -04:00
b64d91108e Update BaseBackgroundHelper.rb
http://www.takeofflabs.com/posts/21-Waiting-for-Background-Jobs
2016-05-25 10:17:11 -04:00
fe063a029e Create BaseBackgroundHelper.rb 2016-05-25 10:14:43 -04:00
b6504333c0 Update qbo_controller.rb 2016-05-25 09:14:28 -04:00
d0c3fefa77 Update qbo_controller.rb 2016-05-25 09:14:10 -04:00
a81e6b9b66 Update qbo.rb 2016-05-25 09:09:22 -04:00
a760ddc7c1 Update customer.rb 2016-05-24 12:34:16 -04:00
3e0b327ea7 Update customer.rb 2016-05-24 12:33:19 -04:00
c5296e7c5f Update customer.rb 2016-05-24 12:04:33 -04:00
fec454f43e Update customer.rb 2016-05-24 12:01:27 -04:00
bd18574bba Update customer.rb 2016-05-24 12:00:02 -04:00
c22272143d Update customer.rb 2016-05-24 11:58:35 -04:00
c3e8fb22c1 Update customer.rb 2016-05-24 11:42:40 -04:00
75defce2dc Update customer.rb 2016-05-24 11:38:55 -04:00
327d59d380 Update customer.rb 2016-05-24 11:35:13 -04:00
10ddd6731e Update customer.rb 2016-05-24 07:51:14 -04:00
181da3fef1 Update customer.rb 2016-05-24 07:33:20 -04:00
fbcc3eba9d Update customer.rb 2016-05-24 07:27:04 -04:00
d265d765d1 Update customer.rb 2016-05-24 06:56:55 -04:00
948c5d0146 Update customer.rb 2016-05-24 06:50:08 -04:00
d0adb4ed4e Less Vehicle Details in List 2016-05-24 06:37:42 -04:00
86cf0b2edd Update customer.rb 2016-05-17 13:47:58 -04:00
4ac76a62a2 Update customer.rb 2016-05-17 13:46:25 -04:00
2995060ec6 Update customer.rb 2016-05-17 13:44:04 -04:00
6e092922ac Update customer.rb 2016-05-17 13:42:32 -04:00
07b72c9cb1 Update customer.rb 2016-05-17 13:39:00 -04:00
a4904c80a0 Update customer.rb 2016-05-17 13:37:28 -04:00
181b928d19 Update customer.rb 2016-05-17 13:33:02 -04:00
fd8ca2d44d Update customer.rb 2016-05-17 13:28:41 -04:00
c72d375aea Update customer.rb 2016-05-17 13:17:44 -04:00
68e3a7cc7c Update customer.rb 2016-05-17 13:13:20 -04:00
69d047e687 Update customer.rb 2016-05-17 13:11:37 -04:00
12166839b2 Update customer.rb 2016-05-17 13:06:58 -04:00
dfb59025f6 Update customer.rb 2016-05-17 13:03:49 -04:00
684e7a45aa Update customer.rb 2016-05-17 13:00:59 -04:00
7503c68820 Update customer.rb 2016-05-17 12:59:37 -04:00
dcfe88b447 Update customer.rb 2016-05-17 12:47:17 -04:00
b5eb3e2568 Update customer.rb 2016-05-17 12:46:55 -04:00
8cf39301bd Update customer.rb 2016-05-17 12:40:53 -04:00
0bb97a4e37 Update qbo_item.rb 2016-05-17 12:30:14 -04:00
1fe10d53dd Update qbo_item.rb 2016-05-17 12:29:25 -04:00
c6b234bde1 Update customer.rb 2016-05-17 11:52:41 -04:00
68169de61d Update customer.rb 2016-05-17 11:48:58 -04:00
e82d09c027 Update qbo_controller.rb 2016-05-17 11:42:50 -04:00
65a89407ff Update customer.rb 2016-05-17 11:34:02 -04:00
76778ece82 Update customer.rb 2016-05-17 11:31:01 -04:00
dfbf5ab1af Update qbo_item.rb 2016-05-17 11:21:44 -04:00
b771199e3d Update qbo_item.rb 2016-05-17 11:06:10 -04:00
a715434f42 Update customer.rb 2016-05-17 11:03:22 -04:00
7009387a00 Update customer.rb 2016-05-17 10:56:31 -04:00
5117e7a479 Update customer.rb 2016-05-17 10:54:03 -04:00
cae904b5a8 Update customer.rb 2016-05-17 10:48:59 -04:00
9876ebf6ed Update customer.rb 2016-05-17 10:42:19 -04:00
c665f5e27b Update qbo_item.rb 2016-05-17 10:40:44 -04:00
77e5022708 Update qbo_item.rb 2016-05-17 08:01:05 -04:00
a8a97ce748 Update qbo_item.rb 2016-05-17 08:00:12 -04:00
bb9d9e5650 Update qbo_item.rb 2016-05-17 07:57:44 -04:00
c5a461f12a Update qbo_item.rb 2016-05-17 07:54:51 -04:00
4c659f9aca Update qbo_item.rb 2016-05-17 07:48:29 -04:00
7bd74df165 Update qbo_item.rb 2016-05-17 07:45:17 -04:00
5d04a8b246 Update qbo_item.rb 2016-05-17 07:22:20 -04:00
4c847a5435 Update qbo_item.rb 2016-05-17 07:21:03 -04:00
dd79571272 Update qbo_item.rb 2016-05-17 07:16:52 -04:00
b931e2967f Update customer.rb 2016-05-17 07:14:44 -04:00
4ec8ceca1b Update customer.rb 2016-05-17 07:06:22 -04:00
798aea6a8b Update customer.rb 2016-05-16 19:31:36 -04:00
e3fcc8c9be Update customer.rb 2016-05-16 18:23:07 -04:00
30255f1db8 Update customer.rb 2016-05-16 17:44:42 -04:00
24f4e9ecf2 Update customer.rb 2016-05-16 17:39:52 -04:00
454613c1ba Update customer.rb 2016-05-16 17:38:36 -04:00
eeccece2a7 Update customer.rb 2016-05-16 17:30:31 -04:00
c9c49c9425 Update customer.rb 2016-05-16 17:26:54 -04:00
d345365e0b Update customer.rb 2016-05-16 17:19:35 -04:00
897f56eb23 Update issues_form_hook_listener.rb 2016-05-16 17:14:50 -04:00
4db96a1792 Update customer.rb 2016-05-12 16:58:40 -04:00
ae572557a1 Update Gemfile 2016-05-12 12:21:39 -04:00
6605bd9467 Update vehicle.rb 2016-05-12 11:46:51 -04:00
3f352f1f19 Update vehicles_controller.rb 2016-05-12 11:43:52 -04:00
939cd63d41 Update _form.html.erb 2016-05-12 11:42:58 -04:00
42c5eb797e Update _form.html.erb 2016-05-12 11:39:12 -04:00
16bb039917 Update _form.html.erb 2016-05-12 11:37:52 -04:00
2db29e1eec Update customer.rb 2016-05-12 11:36:52 -04:00
843c355a64 Update vehicles_controller.rb 2016-05-12 10:11:34 -04:00
8b7cc3ffb6 Update vehicles_controller.rb 2016-05-12 10:10:58 -04:00
a1135115bc Update vehicles_controller.rb 2016-05-12 10:08:44 -04:00
7c37cda14e Update customers_controller.rb 2016-05-12 09:57:25 -04:00
b1614941af Update index.html.erb 2016-05-12 09:56:29 -04:00
f19daef1d7 Update issues_form_hook_listener.rb 2016-05-12 09:50:43 -04:00
9d5d6d6c26 Update issues_form_hook_listener.rb 2016-05-12 09:42:08 -04:00
72d9bbebd0 Update issues_form_hook_listener.rb 2016-05-12 09:40:55 -04:00
fc6ab6bb4e Update issues_form_hook_listener.rb 2016-05-12 09:40:07 -04:00
1360424d34 Update issues_form_hook_listener.rb 2016-05-12 09:38:41 -04:00
9838b831ec Update issues_form_hook_listener.rb 2016-05-12 09:34:38 -04:00
402f6f1097 Update issues_form_hook_listener.rb 2016-05-12 09:32:39 -04:00
a64dc10471 Update customer.rb 2016-05-12 09:25:23 -04:00
a9dcb183fd Update customer.rb 2016-05-12 09:23:51 -04:00
1259abc6c7 Update customer.rb 2016-05-12 09:22:22 -04:00
77438191fe Update customer.rb 2016-05-12 09:20:57 -04:00
0c2b6a8134 Rename config/initializers/without_callback.rb to app/helpers/without_callback.rb 2016-05-12 09:19:11 -04:00
b2c3e31671 Update customer.rb 2016-05-12 09:17:29 -04:00
8e62740d4d Update issues_form_hook_listener.rb 2016-05-12 09:10:24 -04:00
fc93862528 Update vehicles_controller.rb 2016-05-12 09:06:03 -04:00
a68c7d5803 Create without_callback.rb 2016-05-12 09:03:47 -04:00
263030fd93 Update customer.rb 2016-05-11 14:37:31 -04:00
12a6bb575c Update customer.rb 2016-05-11 14:12:08 -04:00
0c2a5c0297 Update customer.rb 2016-05-11 14:03:12 -04:00
64b38aedea Update customer.rb 2016-05-11 13:46:42 -04:00
ad1bd78afe Update customer.rb 2016-05-11 12:50:04 -04:00
74c3535335 Update customers_controller.rb 2016-05-11 12:23:56 -04:00
d8798547b1 Update customer.rb 2016-05-11 12:22:05 -04:00
d48df86a49 Update customer.rb 2016-05-11 12:18:41 -04:00
cd4e21daf4 Update customer.rb 2016-05-11 12:17:25 -04:00
eed8daf87c Update customer.rb 2016-05-11 12:14:34 -04:00
b4c79b08a2 Bring Back The Magic 2016-05-11 12:12:33 -04:00
cec63b48ef Update customer.rb 2016-05-11 12:05:25 -04:00
2ebeef3f42 Update customer.rb 2016-05-11 12:03:23 -04:00
bac9778203 Update customer.rb 2016-05-11 11:57:42 -04:00
0c4b8a24d9 Update customer.rb 2016-05-11 11:56:36 -04:00
476a194410 Update customer.rb 2016-05-11 11:50:33 -04:00
10ec2a1b1b Update customer.rb 2016-05-11 11:47:28 -04:00
936a48f205 Update customer.rb 2016-05-11 11:38:41 -04:00
aba1cdf6d9 Update customer.rb 2016-05-11 11:31:18 -04:00
c80e90b2d4 Update customer.rb 2016-05-11 11:23:21 -04:00
b2e1d649ff Update _form.html.erb 2016-05-11 11:20:42 -04:00
eaf2d9785c Update _form.html.erb 2016-05-11 11:19:24 -04:00
3925337df0 Create edit.html.erb 2016-05-11 11:17:10 -04:00
b35b9cf478 Update _form.html.erb 2016-05-11 11:16:04 -04:00
65577b57dd Update customers_controller.rb 2016-05-11 11:07:34 -04:00
8120296154 Update customers_controller.rb 2016-05-11 11:06:00 -04:00
7a1d769581 Update vehicles_controller.rb 2016-05-11 10:59:44 -04:00
5c9cd88279 Update customers_controller.rb 2016-05-11 09:26:21 -04:00
ec56b59d57 Update vehicles_controller.rb 2016-05-11 09:23:35 -04:00
ee088c65f2 Update vehicles_controller.rb 2016-05-11 09:09:00 -04:00
d7c2ef388f Update _list.html.erb 2016-05-11 09:07:02 -04:00
5a9aaa801a Update show.html.erb 2016-05-11 09:05:15 -04:00
3f06e790f0 Update show.html.erb 2016-05-11 09:04:20 -04:00
1d475185fb Update _form.html.erb 2016-05-11 09:00:58 -04:00
a611afb475 Update vehicles_controller.rb 2016-05-11 09:00:16 -04:00
b65da8e2d9 Update show.html.erb 2016-05-11 08:57:31 -04:00
d9be3323f0 Update _list.html.erb 2016-05-11 08:56:33 -04:00
f04e8e8ab2 Update _details.html.erb 2016-05-11 08:54:54 -04:00
d13609ff4a Update index.html.erb 2016-05-11 07:31:52 -04:00
6305dc73ac Update _details.html.erb 2016-05-11 07:30:37 -04:00
4e61d363ee Update show.html.erb 2016-05-11 07:26:32 -04:00
9fe2119d5a Update _details.html.erb 2016-05-11 07:26:16 -04:00
1500493108 Update customers_controller.rb 2016-05-11 07:25:57 -04:00
6896c94457 Update show.html.erb 2016-05-11 07:23:45 -04:00
13dfca39d3 Update _details.html.erb 2016-05-11 07:22:30 -04:00
7570376f1b Update customer.rb 2016-05-11 07:19:54 -04:00
fc626d4619 Update customer.rb 2016-05-11 07:14:36 -04:00
b77c4eaf37 Update customer.rb 2016-05-11 06:42:29 -04:00
c1ab2848df Update customer.rb 2016-05-11 06:30:18 -04:00
6318c2f7e0 Update customers_controller.rb 2016-05-11 05:52:04 -04:00
1d5bf9f1c9 Update show.html.erb 2016-05-10 07:25:48 -04:00
8447de006a Update _form.html.erb 2016-05-10 05:51:21 -04:00
82bab537b5 Update _form.html.erb 2016-05-10 05:46:08 -04:00
c74c40f08d Update _form.html.erb 2016-05-10 05:43:18 -04:00
e2d8f2f16c Update _list.html.erb 2016-05-10 05:30:02 -04:00
7f2a918f9e Update _details.html.erb 2016-05-10 05:23:56 -04:00
0b2fbba330 Update _list.html.erb 2016-05-10 05:23:22 -04:00
4df82ea8e1 Update show.html.erb 2016-05-10 05:15:06 -04:00
3af5e28c9e Update show.html.erb 2016-05-10 05:10:38 -04:00
319df60b51 Update vehicles_controller.rb 2016-05-10 05:09:25 -04:00
cf30ff3fe1 Update vehicles_controller.rb 2016-05-10 05:07:19 -04:00
767f42c326 Update show.html.erb 2016-05-10 05:06:26 -04:00
51c90f5fef Update issues_form_hook_listener.rb 2016-05-09 09:10:31 -04:00
b82849938d Update issues_form_hook_listener.rb 2016-05-09 09:08:35 -04:00
1adfaa1fdb Update vehicles_controller.rb 2016-05-09 09:04:41 -04:00
1542697ca1 Update issues_show_hook_listener.rb 2016-05-09 07:39:00 -04:00
9c63ffc08a Update issues_show_hook_listener.rb 2016-05-09 07:33:46 -04:00
9e331b83d3 Update issues_show_hook_listener.rb 2016-05-09 07:32:48 -04:00
e3d4be434b Update issues_show_hook_listener.rb 2016-05-09 07:31:18 -04:00
f919ae9b00 Update issues_show_hook_listener.rb 2016-05-09 07:27:37 -04:00
8fdcf7fb43 Update issues_show_hook_listener.rb 2016-05-09 07:26:38 -04:00
3fcb49a56b Update issue_patch.rb 2016-05-09 07:25:06 -04:00
53629c59c3 Update issues_show_hook_listener.rb 2016-05-09 07:10:11 -04:00
7976c033ad Update vehicle.rb 2016-05-09 07:06:17 -04:00
0627722806 Update vehicle.rb 2016-05-09 06:51:19 -04:00
903ae789d2 Update _details.html.erb 2016-05-09 06:49:38 -04:00
8d5154a456 Update _form.html.erb 2016-05-09 06:48:21 -04:00
b002730a95 Update vehicle.rb 2016-05-09 06:46:48 -04:00
20d3d61d1d Update vehicle.rb 2016-05-09 05:01:41 -04:00
8e6c5f81a1 Update vehicles_controller.rb 2016-05-06 12:27:01 -04:00
a70561b5bd Update vehicles_controller.rb 2016-05-06 12:25:30 -04:00
5d6ff72ef7 Update vehicles_controller.rb 2016-05-06 12:20:00 -04:00
039e9f97c6 Update vehicles_controller.rb 2016-05-06 12:18:48 -04:00
3896560184 Update vehicles_controller.rb 2016-05-06 12:17:33 -04:00
3d9c7f8ad9 Update vehicles_controller.rb 2016-05-06 12:16:30 -04:00
d70ce7b156 Update vehicles_controller.rb 2016-05-06 12:10:45 -04:00
a939804dd5 Update customers_controller.rb 2016-05-06 12:10:04 -04:00
b6ee0bb482 Update vehicles_controller.rb 2016-05-06 12:07:49 -04:00
a0b0c3762a Update vehicles_controller.rb 2016-05-06 12:04:54 -04:00
6134906fdd Update vehicles_controller.rb 2016-05-06 12:03:43 -04:00
1af02ec3de Update vehicle.rb 2016-05-06 11:59:30 -04:00
757ddf87ac Update vehicle.rb 2016-05-06 11:37:01 -04:00
5fb42e8cd8 Update vehicle.rb 2016-05-06 10:36:50 -04:00
836653fc38 Update vehicle.rb 2016-05-06 07:19:46 -04:00
604dd0830e Update vehicles_controller.rb 2016-05-06 07:09:22 -04:00
3427b00e25 Update vehicles_controller.rb 2016-05-06 07:06:04 -04:00
ecaa0cda6a Update vehicles_controller.rb 2016-05-06 07:02:15 -04:00
822dc4b705 Update vehicles_controller.rb 2016-05-06 06:59:21 -04:00
259a4fdc58 Update customers_controller.rb 2016-05-06 06:58:55 -04:00
29ea58db36 Update customers_controller.rb 2016-05-06 06:56:53 -04:00
b217126316 Update vehicle.rb 2016-05-06 06:55:29 -04:00
5dd7de79ab Update vehicle.rb 2016-05-06 06:53:56 -04:00
dd280ddf51 Update vehicle.rb 2016-05-06 06:49:57 -04:00
2210b11a57 Update vehicle.rb 2016-05-06 06:45:55 -04:00
70cd5a5cdd Update vehicles_controller.rb 2016-05-06 06:30:01 -04:00
23d4debc3a Update vehicle.rb 2016-05-06 06:21:45 -04:00
1a708a8a56 Update _form.html.erb 2016-05-06 06:13:37 -04:00
2bb87b74da Update qbo_item.rb 2016-05-04 08:01:54 -04:00
ccff5a5e8a Update customers_controller.rb 2016-05-02 14:35:54 -04:00
573502ee77 Update qbo_invoice.rb 2016-05-02 14:08:26 -04:00
a020231224 Update customer.rb 2016-05-02 14:07:14 -04:00
a1530fb952 Update qbo_item.rb 2016-05-02 14:06:44 -04:00
98bbad8471 Update qbo_invoice.rb 2016-05-02 14:05:46 -04:00
3de06cad11 Update customer.rb 2016-05-02 14:03:32 -04:00
6f5b903e5d Update customer.rb 2016-05-02 14:02:13 -04:00
5b6043a5de Update qbo.rb 2016-05-02 13:41:48 -04:00
0d6240c089 Update qbo_purchase.rb 2016-05-02 13:40:31 -04:00
56a3b2cffb Update qbo_purchase.rb 2016-05-02 13:39:12 -04:00
ca2992e334 Update qbo_item.rb 2016-05-02 13:38:54 -04:00
9def9eb2c3 Update qbo_invoice.rb 2016-05-02 13:38:38 -04:00
81b0902378 Update qbo_estimate.rb 2016-05-02 13:38:20 -04:00
d4a747e3a8 Update qbo_employee.rb 2016-05-02 13:38:03 -04:00
a24f9b78b5 Update customer.rb 2016-05-02 13:36:32 -04:00
5d2acdac08 Update customer.rb 2016-05-02 13:33:08 -04:00
f0b6c237cc Update customer.rb 2016-05-02 13:32:02 -04:00
aea9bf5f40 Update customer.rb 2016-05-02 13:29:47 -04:00
97c65b703f Update customer.rb 2016-05-02 13:28:05 -04:00
23b06ced47 Update customer.rb 2016-05-02 13:13:53 -04:00
c5164684ac Update customer.rb 2016-05-02 13:10:52 -04:00
0304acd2b2 Update customer.rb 2016-05-02 13:03:37 -04:00
86327723b8 Update customer.rb 2016-05-02 13:02:11 -04:00
40f4e6e00e Update qbo_purchase.rb 2016-05-02 13:00:42 -04:00
49a42d2374 Update qbo_item.rb 2016-05-02 13:00:10 -04:00
75f5cd2619 Update qbo_invoice.rb 2016-05-02 12:59:54 -04:00
be95de7066 Update qbo_estimate.rb 2016-05-02 12:59:37 -04:00
3189d227fc Update qbo_employee.rb 2016-05-02 12:59:12 -04:00
a4a043a2d9 Update customer.rb 2016-05-02 12:58:40 -04:00
19f1ffa89c Update qbo_controller.rb 2016-05-02 12:58:10 -04:00
f51fa5c7d0 Update qbo_controller.rb 2016-05-02 12:55:56 -04:00
813a74d1af Update index.html.erb 2016-05-02 12:54:10 -04:00
a55f3e03de Update and rename 20_update_qbos.rb to 20_update_qbos_time_stamp.rb 2016-05-02 12:52:14 -04:00
89e3e50a64 Update and rename 20_update_qbo.rb to 20_update_qbos.rb 2016-05-02 12:51:09 -04:00
6e60b11be1 Update customer.rb 2016-05-02 12:41:15 -04:00
c9225e028c Update qbo_controller.rb 2016-05-02 12:20:50 -04:00
16ed209cc9 Update qbo.rb 2016-05-02 12:19:13 -04:00
47f6a0fa79 Update qbo.rb 2016-05-02 12:18:47 -04:00
e935f514c1 Create 20_update_qbo.rb 2016-05-02 12:15:28 -04:00
55913d3b5a Update customer.rb 2016-05-02 12:11:11 -04:00
781a1bfe61 Update customer.rb 2016-05-02 10:57:30 -04:00
b6f0b35bf0 Create new.html.erb 2016-05-02 10:17:53 -04:00
7d3c21771f Create _form.html.erb 2016-05-02 09:24:52 -04:00
e26b593702 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2016-05-02 08:24:49 -04:00
28324eb6ff Bug Fix 2016-05-02 08:24:17 -04:00
fea0979030 Update vehicles_controller.rb 2016-04-29 09:59:49 -04:00
346fddad27 Update customer.rb 2016-04-29 09:59:21 -04:00
a66adfc6d1 Update vehicles_controller.rb 2016-04-29 09:46:23 -04:00
53a35e0fc3 Update _form.html.erb 2016-04-29 09:44:01 -04:00
325e8cd71c Update vehicles_controller.rb 2016-04-29 09:43:20 -04:00
8c6d5acea1 Update _form.html.erb 2016-04-29 09:15:38 -04:00
832b948f80 Update _form.html.erb 2016-04-29 09:11:46 -04:00
cba21fa1b6 Update _form.html.erb 2016-04-29 09:03:47 -04:00
1934ec9cfc Update _form.html.erb 2016-04-29 09:01:15 -04:00
783b63c9a0 Update _form.html.erb 2016-04-29 08:59:28 -04:00
f9a31fd3f2 Update _form.html.erb 2016-04-29 08:57:43 -04:00
090fbba6f5 Update customer.rb 2016-04-29 08:56:05 -04:00
92baf905cd Update customer.rb 2016-04-29 08:47:39 -04:00
22241a3be4 Update customer.rb 2016-04-29 08:45:44 -04:00
ed27fc559d Update customer.rb 2016-04-29 08:43:14 -04:00
cb07f397e0 Update customer.rb 2016-04-29 08:40:32 -04:00
916a9bdb70 Update customer.rb 2016-04-29 08:38:15 -04:00
9750ef2f3b Update customer.rb 2016-04-29 08:34:02 -04:00
ab6851ff2b Update customer.rb 2016-04-29 08:29:29 -04:00
ebf0177dd7 Update customer.rb 2016-04-29 08:25:42 -04:00
a8ce05d8a6 Update vehicle.rb 2016-04-29 07:26:30 -04:00
43876fb61d Update vehicle.rb 2016-04-29 07:14:34 -04:00
5b87733b54 Update customer.rb 2016-04-29 06:57:00 -04:00
0497220c68 Update issues_show_hook_listener.rb 2016-04-28 14:27:15 -04:00
9d3cbfa2e0 Update issues_show_hook_listener.rb 2016-04-28 14:26:33 -04:00
240b5de58b Update issues_show_hook_listener.rb 2016-04-28 14:24:54 -04:00
0a98e7cb74 Update issues_show_hook_listener.rb 2016-04-28 14:23:48 -04:00
04f64eadc7 Update issues_show_hook_listener.rb 2016-04-28 14:22:31 -04:00
b5b30b2b03 Update query_patch.rb 2016-04-28 13:26:04 -04:00
f96f01784a Update en.yml 2016-04-28 12:29:02 -04:00
fa09a50e84 Update _form.html.erb 2016-04-28 12:26:33 -04:00
923d09328b Update _list.html.erb 2016-04-28 12:25:21 -04:00
5a7cfbd2a6 Update 019_qbocustomers_to_customers.rb 2016-04-28 12:22:23 -04:00
d2d61b5e87 Update 019_qbocustomers_to_customers.rb 2016-04-28 12:17:41 -04:00
253c566e90 Update issues_save_hook_listener.rb 2016-04-28 12:14:30 -04:00
39d2e172bc Update query_patch.rb 2016-04-28 12:11:22 -04:00
1bddea1e8f Update qbo_controller.rb 2016-04-28 12:08:41 -04:00
e928ad58dc Update qbo_helper.rb 2016-04-28 12:07:13 -04:00
002e62f723 Update qbo_helper.rb 2016-04-28 12:07:04 -04:00
d809e90627 Update 019_qbocustomers_to_customers.rb 2016-04-28 12:06:22 -04:00
150e18a2d0 Update pdf_patch.rb 2016-04-28 12:04:14 -04:00
4155547fb9 Update issues_show_hook_listener.rb 2016-04-28 12:03:28 -04:00
108ed72560 Update issues_form_hook_listener.rb 2016-04-28 12:02:17 -04:00
701112311d Update issues_form_hook_listener.rb 2016-04-28 12:01:04 -04:00
5f2c6d2c20 Update issue_patch.rb 2016-04-28 12:00:04 -04:00
e70adfd335 Update init.rb 2016-04-28 11:59:04 -04:00
a9ebc4107f Update customers_controller.rb 2016-04-28 11:58:24 -04:00
76ffda9cad Update vehicles_controller.rb 2016-04-28 11:57:54 -04:00
b5d42fcd7b Rename Customer 2016-04-28 11:56:45 -04:00
11e215189b Update and rename qbo_customer.rb to customer.rb 2016-04-28 11:55:40 -04:00
1e426a8295 Create 019_qbocustomers_to_customers.rb 2016-04-28 11:54:01 -04:00
8aa3240c7e Update README.md 2016-04-28 11:48:10 -04:00
41 changed files with 710 additions and 344 deletions

View File

@@ -2,9 +2,8 @@ source 'https://rubygems.org'
gem 'quickbooks-ruby'
gem 'quickbooks-ruby-base'
gem 'oauth-plugin'#, '~> 0.5.1'
gem 'oauth-plugin'
gem 'oauth'
gem 'roxml'
gem 'nokogiri'
gem 'edmunds_vin'
gem 'will_paginate', '~> 3.1.0'

View File

@@ -53,9 +53,9 @@ Note: Customers, Employees, and Service Items with automaticly update during nor
## TODO
* Abiltiy to add line items to a ticket in a dynamic table so they can be added to the invoice upon closing of the issue
* Customer ~~Creation~~, ~~Update~~, Deletion
* Email Customer updates, provding a link that would: bypass the login page, go directly to the issue directing them to, and allow them to view only that issue.
* Add a rake file to create required Trackers or statuses required
* Add link Invoice PDF to issue after creation.
* Clean up view hook code, possibly use a controller hook and reder partial views
* Add Setting for Sandbox Mode
##License

View File

@@ -18,46 +18,68 @@ class CustomersController < ApplicationController
# display a list of all customers
def index
@customers = QboCustomer.paginate(:page => params[:page])
@customers = Customer.paginate(:page => params[:page])
end
def new
@customer = Customer.new
end
def create
@customer = Customer.new(params[:customer])
if @customer.save
flash[:notice] = "New Customer Created"
redirect_to @customer
else
flash[:error] = @customer.errors.full_messages.to_sentence
redirect_to new_customer_path
end
end
# display a specific customer
def show
@customer = QboCustomer.find_by_id(params[:id])
if @customer
begin
@customer = Customer.find_by_id(params[:id])
@vehicles = @customer.vehicles.paginate(:page => params[:page])
else
flash[:error] = "Customer Not Found"
render :index
@issues = @customer.issues
rescue ActiveRecord::RecordNotFound
render_404
end
end
# return an HTML form for editing a customer
def edit
@customer = QboCustomer.find_by_id(params[:id])
begin
@customer = Customer.find_by_id(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# update a specific customer
def update
@customer = QboCustomer.find_by_id(params[:id])
if @customer.update_attributes(params[:customer])
flash[:success] = "Customer updated"
redirect_to @customer
else
render :edit
begin
@customer = Customer.find_by_id(params[:id])
if @customer.update_attributes(params[:customer])
flash[:notice] = "Customer updated"
redirect_to @customer
else
redirect_to edit_customer_path
flash[:error] = @customer.errors.full_messages.to_sentence if @customer.errors
end
rescue ActiveRecord::RecordNotFound
render_404
end
end
def destroy
begin
Customer.find_by_id(params[:id]).destroy
flash[:notice] = "Customer deleted successfully"
redirect_to action: :index
rescue ActiveRecord::RecordNotFound
render_404
end
end
end

View File

@@ -13,14 +13,15 @@ class QboController < ApplicationController
include AuthHelper
before_filter :require_user
before_filter :require_user, :except => :qbo_webhook
skip_before_filter :verify_authenticity_token, :check_if_login_required
#
# Called when the QBO Top Menu us shown
#
def index
@qbo = Qbo.first
@qbo_customer_count = QboCustomer.count
@customer_count = Customer.count
@qbo_item_count = QboItem.count
@qbo_employee_count = QboEmployee.count
@qbo_invoice_count = QboInvoice.count
@@ -31,9 +32,10 @@ class QboController < ApplicationController
# Called when the user requests that Redmine to connect to QBO
#
def authenticate
callback = request.base_url + qbo_oauth_callback_path
callback = qbo_oauth_callback_url
token = Qbo.get_oauth_consumer.get_request_token(:oauth_callback => callback)
session[:qb_request_token] = token
#session[:qb_request_token] = token
session[:qb_request_token] = Marshal.dump(token)
redirect_to("https://appcenter.intuit.com/Connect/Begin?oauth_token=#{token.token}") and return
end
@@ -41,40 +43,77 @@ class QboController < ApplicationController
# Called by QBO after authentication has been processed
#
def oauth_callback
at = session[:qb_request_token].get_access_token(:oauth_verifier => params[:oauth_verifier])
token = at.token
secret = at.secret
realm_id = params['realmId']
#at = session[:qb_request_token].get_access_token(:oauth_verifier => params[:oauth_verifier])
# If Rails >= 4.1 you need to do this =>
at = Marshal.load(session[:qb_request_token]).get_access_token(:oauth_verifier => params[:oauth_verifier])
#There can only be one...
Qbo.destroy_all
# Save the authentication information
qbo = Qbo.new
qbo.token = token
qbo.secret = secret
qbo.qb_token = at.token
qbo.qb_secret = at.secret
qbo.token_expires_at = 6.months.from_now.utc
qbo.reconnect_token_at = 5.months.from_now.utc
qbo.realmId = realm_id
qbo.company_id = params['realmId']
if qbo.save!
redirect_to qbo_sync_path, :flash => { :notice => "Successfully connected to Quickbooks" }
redirect_to qbo_path, :flash => { :notice => "Successfully connected to Quickbooks" }
else
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => "Error" }
end
end
# Quickbooks Webhook Callback
def qbo_webhook
if request.headers['Content-Type'] == 'application/json'
data = JSON.parse(request.body.read)
else
# application/x-www-form-urlencoded
data = params.as_json
end
entities = data['eventNotifications'][0]['dataChangeEvent']['entities']
entities.each do |entity|
if entity['name'].eql? "Customer"
Customer.sync_by_id(entity['id'].to_i)
end
if entity['name'].eql? "Invoice"
QboInvoice.sync_by_id(entity['id'].to_i)
end
if entity['name'].eql? "Estimate"
QboEstimate.sync_by_id(entity['id'].to_i)
end
if entity['name'].eql? "Employee"
QboEmployee.sync_by_id(entity['id'].to_i)
end
end
# The webhook doesn't require a response but let's make sure
# we don't send anything
render :nothing => true
end
#
# Synchronizes the QboCustomer table with QBO
#
def sync
if Qbo.exists?
QboCustomer.update_all
QboItem.update_all
QboEmployee.update_all
QboEstimate.update_all
QboInvoice.update_all
QboPurchase.update_all
Customer.sync
QboItem.sync
QboEmployee.sync
QboEstimate.sync
QboInvoice.sync
#QboPurchase.sync
# Record the last sync time
Qbo.update_time_stamp
end
redirect_to qbo_path(:redmine_qbo), :flash => { :notice => "Successfully synced to Quickbooks" }

View File

@@ -24,53 +24,67 @@ class VehiclesController < ApplicationController
# return an HTML form for creating a new vehicle
def new
@vehicle = Vehicle.new
@customers = Customer.all.order(:name)
end
# create a new vehicle
def create
@vehicle = Vehicle.new(params[:vehicle])
@vehicle.save!
redirect_to @vehicle
if @vehicle.save
flash[:notice] = "New Vehicle Created"
redirect_to @vehicle
else
flash[:error] = @vehicle.errors.full_messages.to_sentence
redirect_to new_vehicle_path
end
end
# display a specific vehicle
def show
@vehicle = Vehicle.find_by_id(params[:id])
if @vehicle
@customer = @vehicle.qbo_customer.name if @vehicle.qbo_customer
else
flash[:error] = "Vehicle Not Found"
render :index
begin
@vehicle = Vehicle.find_by_id(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
# return an HTML form for editing a vehicle
def edit
@vehicle = Vehicle.find_by_id(params[:id])
@customer = @vehicle.qbo_customer.id if @vehicle.qbo_customer
begin
@vehicle = Vehicle.find_by_id(params[:id])
@customer = @vehicle.customer.id
@customers = Customer.all.order(:name)
rescue ActiveRecord::RecordNotFound
render_404
end
end
# update a specific vehicle
def update
@vehicle = Vehicle.find_by_id(params[:id])
if @vehicle.update_attributes(params[:vehicle])
flash[:success] = "Vehicle updated"
redirect_to @vehicle
else
render :edit
@customer = params[:customer]
begin
@vehicle = Vehicle.find_by_id(params[:id])
if @vehicle.update_attributes(params[:vehicle])
flash[:notice] = "Vehicle updated"
redirect_to @vehicle
else
flash[:error] = @vehicle.errors.full_messages.to_sentence if @vehicle.errors
redirect_to edit_vehicle_path
end
rescue ActiveRecord::RecordNotFound
render_404
end
end
# delete a specific vehicle
def destroy
v = Vehicle.find_by_id(params[:id])
if v != nil
v.destroy
flash.now[:notice] = "Vehicle deleted successfully"
else
flash.now[:error] = "No Vehicle Found"
def destroy
begin
Vehicle.find_by_id(params[:id]).destroy
flash[:notice] = "Vehicle deleted successfully"
redirect_to action: :index
rescue ActiveRecord::RecordNotFound
render_404
end
redirect_to action: :index
end
end

View File

@@ -1,2 +0,0 @@
module EstimateHelper
end

View File

@@ -1,2 +0,0 @@
module InvoiceHelper
end

View File

@@ -8,11 +8,10 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module QboHelper
def qbo_customer_dropdown
select = context[:form].select :qbo_customer_id, QboCustomers.all.pluck(:name, :id), :selected => selected, include_blank: true
return "<p>#{select}</p>"
end
module ActiveSupport::Callbacks::ClassMethods
def without_callback(*args, &block)
skip_callback(*args)
yield
set_callback(*args)
end
end

190
app/models/customer.rb Normal file
View File

@@ -0,0 +1,190 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class Customer < ActiveRecord::Base
unloadable
has_many :issues
has_many :qbo_purchases
has_many :vehicles
attr_accessible :name, :notes, :email, :primary_phone, :mobile_phone
validates_presence_of :id, :name
self.primary_key = :id
# returns a human readable string
def to_s
return name
end
# Convenience Method
# returns the customer's email
def email
pull unless @details
begin
return @details.email_address.address
rescue
return nil
end
end
# Convenience Method
# Sets the email
def email=(s)
pull unless @details
@details.email_address = s
end
# Convenience Method
# returns the customer's primary phone
def primary_phone
pull unless @details
begin
return @details.primary_phone.free_form_number
rescue
return nil
end
end
# Convenience Method
# Updates the customer's primary phone number
def primary_phone=(n)
pull unless @details
pn = Quickbooks::Model::TelephoneNumber.new
pn.free_form_number = n
@details.primary_phone = pn
end
# Convenience Method
# returns the customer's mobile phone
def mobile_phone
pull unless @details
begin
return @details.mobile_phone.free_form_number
rescue
return nil
end
end
# Convenience Method
# Updates the custome's mobile phone number
def mobile_phone=(n)
pull unless @details
pn = Quickbooks::Model::TelephoneNumber.new
pn.free_form_number = n
@details.mobile_phone = pn
end
# Convenience Method
# Updates Both local DB name & QBO display_name
def name=(s)
pull unless @details
@details.display_name = s
super
end
# Magic Method
# Maps Get/Set methods to QBO customer object
def method_missing(sym, *arguments)
# Check to see if the method exists
if Quickbooks::Model::Customer.method_defined?(sym)
# download details if required
pull unless @details
method_name = sym.to_s
# Setter
if method_name[-1, 1] == "="
@details.method(method_name).call(arguments[0])
# Getter
else
return @details.method(method_name).call
end
end
end
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync
service = Qbo.get_base(:customer).service
# Sync ALL customers if the database is empty
#if count == 0
customers = service.all
#else
# last = Qbo.first.last_sync
# query = "Select Id, DisplayName From Customer"
# query << " Where Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
# customers = service.query(query)
#end
customers.each do |customer|
qbo_customer = Customer.find_or_create_by(id: customer.id)
if customer.active?
if not qbo_customer.name.eql? customer.display_name
qbo_customer.name = customer.display_name
qbo_customer.id = customer.id
qbo_customer.save_without_push
end
else
if not qbo_customer.new_record?
qbo_customer.delete
end
end
end
end
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync_by_id(id)
service = Qbo.get_base(:customer).service
customer = service.fetch_by_id(id)
qbo_customer = Customer.find_or_create_by(id: customer.id)
if customer.active?
if not qbo_customer.name.eql? customer.display_name
qbo_customer.name = customer.display_name
qbo_customer.id = customer.id
qbo_customer.save_without_push
end
else
if not qbo_customer.new_record?
qbo_customer.delete
end
end
end
# Push the updates
def save_with_push
begin
@details = Qbo.get_base(:customer).service.update(@details)
#raise "QBO Fault" if @details.fault?
self.id = @details.id
rescue Exception => e
errors.add(e.message)
end
save_without_push
end
alias_method :save_without_push, :save
alias_method :save, :save_with_push
private
# pull the details
def pull
begin
raise Exception unless self.id
@details = Qbo.get_base(:customer).find_by_id(self.id)
rescue Exception => e
@details = Quickbooks::Model::Customer.new
end
end
end

View File

@@ -11,24 +11,28 @@
class Qbo < ActiveRecord::Base
unloadable
validates_presence_of :qb_token, :qb_secret, :company_id, :token_expires_at, :reconnect_token_at
QB_KEY = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
QB_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
# Quickbooks Config Info
$qb_oauth_consumer = OAuth::Consumer.new(QB_KEY, QB_SECRET, {
:site => "https://oauth.intuit.com",
:request_token_path => "/oauth/v1/get_request_token",
:authorize_url => "https://appcenter.intuit.com/Connect/Begin",
:access_token_path => "/oauth/v1/get_access_token"
})
OAUTH_CONSUMER_KEY = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
$qb_oauth_consumer = OAuth::Consumer.new(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, {
:site => "https://oauth.intuit.com",
:request_token_path => "/oauth/v1/get_request_token",
:authorize_url => "https://appcenter.intuit.com/Connect/Begin",
:access_token_path => "/oauth/v1/get_access_token"
})
# Configure quickbooks-ruby-base to access our database
Quickbooks::Base.configure do |c|
c.persistent_token = 'qb_token'
c.persistent_secret = 'qb_secret'
c.persistent_company_id = 'company_id'
end
c.persistent_token = 'qb_token'
c.persistent_secret = 'qb_secret'
c.persistent_company_id = 'company_id'
end
def self.get_oauth_consumer
# Quickbooks Config Info
return $qb_oauth_consumer
end
# Get a quickbooks base object for type
# @params type of base
@@ -40,4 +44,11 @@ class Qbo < ActiveRecord::Base
def self.get_account
first
end
# Updates last sync time stamp
def self.update_time_stamp
qbo = Qbo.first
qbo.last_sync = DateTime.now
qbo.save
end
end

View File

@@ -1,128 +0,0 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class QboCustomer < ActiveRecord::Base
unloadable
has_many :issues
has_many :qbo_purchases
has_many :vehicles
attr_accessible :name
validates_presence_of :id, :name
after_initialize :get_details
self.primary_key = :id
# returns true if the customer is active
def active?
return @details.active? if @details
end
# returns a human readable string
def to_s
return name
end
# returns the customer's email
def email
begin
return @details.email_address.address
rescue
return nil
end
end
# returns the customer's primary phone
def primary_phone
begin
return @details.primary_phone.free_form_number
rescue
return nil
end
end
# returns the customer's mobile phone
def mobile_phone
begin
return @details.mobile_phone.free_form_number
rescue
return nil
end
end
# returns the customer's notes
def notes
return @details.notes if @details
end
# updates the customer's notes in QBO
def notes=(s)
customer = get_customer(self.id)
customer.notes = s
get_base.update(customer)
end
# returns the bases QBO service for customers
def get_base
Qbo.get_base(:customer)
end
# returns the QBO customer
def get_customer (id)
get_base.find_by_id(id)
end
# proforms a bruteforce sync operation
# This needs to be simplified
def update_all
customers = get_base.service.all
transaction do
# Update the customer table
customers.each { |customer|
qbo_customer = QboCustomer.find_or_create_by(id: customer.id)
# only update if diffrent
if not qbo_customer.name == customer.display_name
qbo_customer.name = customer.display_name
qbo_customer.id = customer.id
qbo_customer.save!
end
}
end
# remove deleted customers
where.not(customers.map(&:id)).destroy_all
end
private
# init details
def get_details
if self.id
@details = get_customer(self.id)
update
end
end
# update's the customers name if updated
def update
begin
if not self.name == @detils.display_name
self.name = @details.display_name
self.save
end
rescue
return nil
end
end
end

View File

@@ -18,7 +18,7 @@ class QboEmployee < ActiveRecord::Base
Qbo.get_base(:employee)
end
def self.update_all
def self.sync
employees = get_base.service.all
transaction do
@@ -30,8 +30,14 @@ class QboEmployee < ActiveRecord::Base
qbo_employee.save!
}
end
end
def self.sync_by_id(id)
employee = get_base.service.fetch_by_id(id)
#remove deleted employees
where.not(employees.map(&:id)).destroy_all
qbo_employee = find_or_create_by(id: employee.id)
qbo_employee.name = employee.display_name
qbo_employee.id = employee.id
qbo_employee.save!
end
end

View File

@@ -18,7 +18,7 @@ class QboEstimate < ActiveRecord::Base
Qbo.get_base(:estimate)
end
def self.update_all
def self.sync
estimates = get_base.service.all
# Update the item table
@@ -35,6 +35,14 @@ class QboEstimate < ActiveRecord::Base
where.not(estimates.map(&:id)).destroy_all
end
def self.sync_by_id(id)
estimate = get_base.service.fetch_by_id(id)
qbo_estimate = QboEstimate.find_or_create_by(id: estimate.id)
qbo_estimate.doc_number = estimate.doc_number
qbo_estimate.id = estimate.id
qbo_estimate.save!
end
def self.update(id)
# Update the item table
estimate = get_base.service.fetch_by_id(id)

View File

@@ -18,22 +18,39 @@ class QboInvoice < ActiveRecord::Base
Qbo.get_base(:invoice)
end
def self.update_all
def self.sync
#Pull the invoices from the quickbooks server
invoices = get_base.service.all
#invoices = get_base.service.all
last = Qbo.first.last_sync
query = "SELECT Id, DocNumber FROM Invoice"
query << " WHERE Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
if count == 0
invoices = get_base.service.all
else
invoices = get_base.service.query()
end
# Update the invoice table
transaction do
invoices.each { | invoice |
qbo_invoice = find_or_create_by(id: invoice.id)
qbo_invoice.doc_number = invoice.doc_number
qbo_invoice.id = invoice.id
qbo_invoice.save!
}
end
invoices.each { | invoice |
qbo_invoice = find_or_create_by(id: invoice.id)
qbo_invoice.doc_number = invoice.doc_number
qbo_invoice.id = invoice.id
qbo_invoice.save!
}
#remove deleted invoices
where.not(invoices.map(&:id)).destroy_all
#where.not(invoices.map(&:id)).destroy_all
end
def self.sync_by_id(id)
invoice = get_base.service.fetch_by_id(id)
qbo_invoice = find_or_create_by(id: invoice.id)
qbo_invoice.doc_number = invoice.doc_number
qbo_invoice.id = invoice.id
qbo_invoice.save!
end
def self.update(id)

View File

@@ -13,25 +13,35 @@ class QboItem < ActiveRecord::Base
has_many :issues
attr_accessible :name
validates_presence_of :id, :name
self.primary_key = :id
def self.get_base
Qbo.get_base(:item)
end
def self.update_all
items = get_base.service.find_by(:type, "Service")
transaction do
# Update the item table
items.each { |item|
qbo_item = QboItem.find_or_create_by(id: item.id)
qbo_item.name = item.name
qbo_item.id = item.id
qbo_item.save!
def self.sync
last = Qbo.first.last_sync
query = "SELECT Id, Name FROM Item WHERE Type = 'Service' "
query << " AND Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
if count == 0
items = get_base.service.all
else
items = get_base.service.query(query)
end
unless items.count = 0
items.find_by(:type, "Service").each { |i|
qbo_item = QboItem.find_or_create_by(id: i.id)
qbo_item.name = i.name
qbo_item.id = i.id
qbo_item.save
}
end
#remove deleted items
where.not(items.map(&:id)).destroy_all
# QboItem.where.not(items.map(&:id)).destroy_all
end
end

View File

@@ -19,11 +19,11 @@ class QboPurchase < ActiveRecord::Base
Qbo.get_base(:purchase)
end
def self.get_purchase(id)
def get_purchase(id)
get_base.service.find_by_id(id)
end
def self.update_all
def self.sync
QboPurchase.get_base.service.all.each { |purchase|
purchase.line_items.all? { |line_item|

View File

@@ -11,17 +11,26 @@
class Vehicle < ActiveRecord::Base
unloadable
belongs_to :qbo_customer
attr_accessible :year, :make, :model, :qbo_customer_id, :notes, :vin
validates_presence_of :year, :make, :model, :qbo_customer_id
API_KEY = Setting.plugin_redmine_qbo['settingsEdmundsAPIKey']
before_validation :decode_vin
belongs_to :customer
has_many :issues, :foreign_key => 'vehicles_id'
attr_accessible :year, :make, :model, :customer_id, :notes, :vin
validates_presence_of :customer
validates :vin, uniqueness: true
validates :year, numericality: { only_integer: true }
before_save :decode_vin
after_initialize :get_details
self.primary_key = :id
# returns a human readable string
def to_s
return "#{self.year} #{self.make} #{self.model}"
return "#{year} #{make} #{model}"
end
# returns the raw JSON details from EMUNDS
@@ -40,7 +49,7 @@ class Vehicle < ActiveRecord::Base
# returns the drive of the vehicle i.e. 2 wheel, 4 wheel, ect.
def drive
return @details['drivenWheels'] if @details
return @details['drivenWheels'].to_s.upcase if @details
end
# returns the number of doors of the vehicle
@@ -48,29 +57,56 @@ class Vehicle < ActiveRecord::Base
return @details['numOfDoors'] if @details
end
# Force Upper Case for VIN numbers
def make=(val)
# The to_s is in case you get nil/non-string
write_attribute(:make, val.to_s.titleize)
end
# Force Upper Case for VIN numbers
def model=(val)
# The to_s is in case you get nil/non-string
write_attribute(:model, val.to_s.titleize)
end
# Force Upper Case for VIN numbers
def vin=(val)
# The to_s is in case you get nil/non-string
write_attribute(:vin, val.to_s.upcase)
end
private
# init method to pull JSON details from Edmunds
def get_details
if self.vin?
@details = JSON.parse get_decoder.full(self.vin)
begin
@details = JSON.parse get_decoder.full(self.vin)
raise @details['message'] if @details['status'] == "NOT_FOUND"
raise @details['message'] if @details['status'] == "BAD_REQUEST"
rescue Exception => e
errors.add(:vin, e.message)
end
end
end
# returns the Edmunds decoder service
def get_decoder
#TODO API Code via Settings
return decoder = Edmunds::Vin.new('2dheutzvhxs28dzukx5tgu47')
return decoder = Edmunds::Vin.new(API_KEY)
end
# decodes a vin and updates self
def decode_vin
get_details
if self.vin?
details
self.year = @details['years'][0]['year']
self.make = @details['make']['name']
self.model = @details['model']['name']
if @details
begin
self.year = @details['years'][0]['year']
self.make = @details['make']['name']
self.model = @details['model']['name']
rescue Exception => e
errors.add(:vin, e.message)
end
end
self.name = to_s
end

View File

@@ -2,33 +2,38 @@
<tbody>
<tr>
<th>Customer</th>
<td><%= @customer.name %></td>
<td><%= customer.name %></td>
</tr>
<tr>
<th>Email</th>
<td><%= @customer.email %></td>
<td><%= customer.email %></td>
</tr>
<tr>
<th>Primary Phone</th>
<td><%= @customer.primary_phone %></td>
<td><%= customer.primary_phone %></td>
</tr>
<tr>
<th>Mobile Phone</th>
<td><%= @customer.mobile_phone %></td>
<td><%= customer.mobile_phone %></td>
</tr>
<tr>
<th>Notes</th>
<td><%= @customer.notes %></td>
<td><%= customer.notes %></td>
</tr>
<tr>
<th>Issues</th>
<td><%= customer.issues.count %></td>
</tr>
<tr>
<td/>
<td>
<%= button_to "Edit", edit_customer_path(@customer), method: :get%>
<%= button_to "Edit Customer", edit_customer_path(customer), method: :get%>
</td>
</tr>
</tbody>

View File

@@ -0,0 +1,60 @@
<div class="row">
<div class="span6 columns">
<fieldset>
<%= form_for @customer do |f| %>
<div class="clearfix">
Display Name:
<div class="input">
<%= f.text_field :name, :required => true %>
</div>
</div>
<div class="clearfix">
Phone Number:
<div class="input">
<%= f.telephone_field :primary_phone %>
</div>
</div>
<div class="clearfix">
Mobile Phone Number:
<div class="input">
<%= f.telephone_field :mobile_phone %>
</div>
</div>
<div class="clearfix">
Email:
<div class="input">
<%= f.email_field :email %>
</div>
</div>
<div class="clearfix">
Notes:
<div class="input">
<p>
<%= link_to_function content_tag(:span, l(:button_edit), :class => 'icon icon-edit'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @customer.new_record? %>
<%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@customer.new_record? ? nil : 'display:none') do %>
<%= f.text_area :notes,
:cols => 60,
:rows => 10,
:accesskey => accesskey(:edit),
:class => 'wiki-edit',
:no_label => true %>
<% end %>
</p>
<%= wikitoolbar_for 'issue_description' %>
</div>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</fieldset>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<h1>Edit Customer</h1>
<br/>
<%= render :partial => 'customers/form' %>

View File

@@ -4,8 +4,7 @@
<div class="row">
<div class="span6 columns">
<fieldset>
<% @customer = c %>
<%= render :partial => 'customers/details' %>
<%= c.name %>
<%= button_to "Show", customer_path(c.id), method: :get %>
</fieldset>
</div>

View File

@@ -0,0 +1,3 @@
<h1>New Customer</h1>
<br/>
<%= render :partial => 'customers/form' %>

View File

@@ -1,5 +1,7 @@
<h1>Customer Detail</h1>
<br/>
<%= render :partial => 'customers/details' %>
<%= render :partial => 'customers/details', locals: {customer: @customer} %>
<br/>
<%= render :partial => 'vehicles/list' %>
<br/>
<%= render :partial => 'issues/list_simple', locals: {issues: @issues} %>

View File

@@ -10,10 +10,27 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-->
<!-- somewhere in your document include the Javascript -->
<script type="text/javascript" src="https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js"></script>
<!-- configure the Intuit object: 'grantUrl' is a URL in your application which kicks off the flow, see below -->
<script>
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_authenticate_url %>'});
</script>
<table >
<tbody>
<tr>
<th>OAuth Consumer Key</th>
<th>Edmunds API Key</th>
<td>
<input type="text" style="width:350px" id="settingsEdmundsAPIKey"
value="<%= settings['settingsEdmundsAPIKey'] %>"
name="settings[settingsEdmundsAPIKey]" >
</td>
</tr>
<tr>
<th>Intuit QBO OAuth Consumer Key</th>
<td>
<input type="text" style="width:350px" id="settingsOAuthConsumerKey"
value="<%= settings['settingsOAuthConsumerKey'] %>"
@@ -22,7 +39,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
</tr>
<tr>
<th>OAuth Consumer Secret</th>
<th>Intuit QBO OAuth Consumer Secret</th>
<td>
<input type="text" style="width:350px" id="settingsOAuthConsumerSecret"
value="<%= settings['settingsOAuthConsumerSecret'] %>"
@@ -30,14 +47,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
</td>
</tr>
</tbody>
</table>
<br/>
<table>
<tbody>
<tr>
<th>Token Expires At</th>
<td><%= if Qbo.exists? then Qbo.first.token_expires_at end %>
@@ -54,5 +63,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<br/>
Note: You need to authenticate after saving your key and secret above
<br/>
<%= link_to "Authenticate", qbo_authenticate_path, :method => :get %>
<!-- this will display a button that the user clicks to start the flow -->
<ipp:connectToIntuit></ipp:connectToIntuit>

View File

@@ -14,9 +14,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<h1> Redmine Quickbooks</h1>
<%= form_for @qbo do |f|%>
<div>
<%= f.label "Customer Count:"+@qbo_customer_count.to_s%>
<%= f.label "Customer Count:"+@customer_count.to_s%>
<br/>
<%= f.select :qbo_customer_id, QboCustomer.all.pluck(:name, :id).sort, :selected => @selected_customer, include_blank: true %>
<%= f.select :customer_id, Customer.all.pluck(:name, :id).sort, :selected => @selected_customer, include_blank: true %>
</div>
<br/>

View File

@@ -1,45 +1,53 @@
<table>
<tbody>
<tr>
<th>Customer</th>
<td><%= @customer %></td>
<td><%= vehicle.customer.name %></td>
</tr>
<tr>
<th>Vehicle</th>
<td><%= @vehicle.to_s %></td>
<td><%= vehicle.to_s %></td>
</tr>
<tr>
<th>VIN</th>
<td><%= @vehicle.vin %></td>
<td><%= vehicle.vin %></td>
</tr>
<tr>
<th>Style</th>
<td><%= @vehicle.style %></td>
<td><%= vehicle.style %></td>
</tr>
<tr>
<th>Drive</th>
<td><%= @vehicle.drive %></td>
<td><%= vehicle.drive %></td>
</tr>
<tr>
<th>Doors</th>
<td><%= @vehicle.doors %></td>
<td><%= vehicle.doors %></td>
</tr>
<tr>
<th>Notes</th>
<td><%= @vehicle.notes %></td>
<td><%= vehicle.notes %></td>
</tr>
<tr>
<th>Issues</th>
<td><%= vehicle.issues.count %></td>
</tr>
<tr>
<td/>
<td>
<%= button_to "Edit", edit_vehicle_path(@vehicle), method: :get%>
<%= button_to "Delete", @vehicle, method: :delete, data: {confirm: "You sure?"} %>
<%= button_to "New Issue", new_issue_path(:vehicle_id => vehicle.id, :customer_id => vehicle.customer.id), method: :get%>
<%= button_to "Edit", edit_vehicle_path(vehicle), method: :get%>
<%= button_to "Delete", vehicle, method: :delete, data: {confirm: "You sure?"} %>
</td>
</tr>
</tbody>

View File

@@ -6,28 +6,28 @@
<div class="clearfix">
Customer:
<div class="input">
<%= f.collection_select :qbo_customer_id, QboCustomer.order(:name), :id, :name, include_blank: true, :selected => @customer, :required => true%>
<%= f.collection_select :customer_id, @customers, :id, :name, include_blank: true, :selected => @customer, :required => true%>
</div>
</div>
<div class="clearfix">
Year:
<div class="input">
<%= f.text_field :year, :required => true %>
<%= f.number_field :year %>
</div>
</div>
<div class="clearfix">
Make:
<div class="input">
<%= f.text_field :make, :required => true %>
<%= f.text_field :make %>
</div>
</div>
<div class="clearfix">
Model:
<div class="input">
<%= f.text_field :model, :required => true %>
<%= f.text_field :model %>
</div>
</div>
@@ -41,7 +41,18 @@
<div class="clearfix">
Notes:
<div class="input">
<%= f.text_area :notes, :rows => 6, :class => 'wiki-edit', :accesskey => accesskey(:edit), :cols => 60%>
<p>
<%= link_to_function content_tag(:span, l(:button_edit), :class => 'icon icon-edit'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @vehicle.new_record? %>
<%= content_tag 'span', :id => "issue_description_and_toolbar", :style => (@vehicle.new_record? ? nil : 'display:none') do %>
<%= f.text_area :notes,
:cols => 60,
:rows => 10,
:accesskey => accesskey(:edit),
:class => 'wiki-edit',
:no_label => true %>
<% end %>
</p>
<%= wikitoolbar_for 'issue_description' %>
</div>
</div>

View File

@@ -2,9 +2,11 @@
<div class="row">
<div class="span6 columns">
<fieldset>
<% @customer = vehicle.qbo_customer.name if vehicle.qbo_customer %>
<% @vehicle = vehicle %>
<%= render :partial => 'vehicles/details' %>
<%= vehicle.to_s %>
<br/>
<div style="float: right;" >
<%= button_to "More", vehicle_path(vehicle), method: :get %>
</div>
</fieldset>
</div>
</div>
@@ -14,5 +16,5 @@
<div class="actions">
<%= will_paginate @vehicles %>
<%= button_to "New", new_vehicle_path, method: :get %>
<%= button_to "New Vehicle", new_vehicle_path, method: :get %>
</div>

View File

@@ -1,3 +1,8 @@
<h1>Customer Vehicle</h1>
<br/>
<%= render :partial => 'vehicles/details' %>
<div style="text-align: left; width:90%;">
<%= render :partial => 'vehicles/details', locals: {vehicle: @vehicle} %>
<%= render :partial => 'issues/list_simple', locals: {issues: @vehicle.issues} %>
</div>

View File

@@ -11,7 +11,7 @@
# English strings go here for Rails i18n
en:
# my_label: "My label"
field_qbo_customer: "Customer"
field_customer: "Customer"
field_qbo_item: "Item"
field_qbo_employee: "Employee"
field_qbo_invoice: "Invoice"

View File

@@ -17,5 +17,8 @@ get 'qbo/oauth_callback', :to => 'qbo#oauth_callback'
get 'qbo/sync', :to => 'qbo#sync'
get 'qbo/estimate/:id', :to => 'estimate#show', as: :estimate
get 'qbo/invoice/:id', :to => 'invoice#show', as: :invoice
post 'qbo/webhook', :to => 'qbo#qbo_webhook'
resources :vehicles
resources :customers

View File

@@ -0,0 +1,17 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class QbocustomersToCustomers< ActiveRecord::Migration
def change
rename_table :qbo_customers, :customers
rename_column :issues, :qbo_customer_id, :customer_id
rename_column :vehicles, :qbo_customer_id, :customer_id
end
end

View File

@@ -8,6 +8,8 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module VehicleHelper
class UpdateQbosTimeStamp < ActiveRecord::Migration
def change
add_column :qbos, :last_sync, :datetime
end
end

View File

@@ -25,13 +25,13 @@ Redmine::Plugin.register :redmine_qbo do
name 'Redmine Quickbooks Online plugin'
author 'Rick Barrette'
description 'This is a plugin for Redmine to intergrate with Quickbooks Online to allow for seamless intergration CRM and invoicing of completed issues'
version '0.0.5'
version '0.0.7'
url 'https://github.com/rickbarrette/redmine_qbo'
author_url 'http://rickbarrette.org'
settings :default => {'empty' => true}, :partial => 'qbo/settings'
# Add safe attributes
Issue.safe_attributes 'qbo_customer_id'
Issue.safe_attributes 'customer_id'
Issue.safe_attributes 'qbo_item_id'
Issue.safe_attributes 'qbo_estimate_id'
Issue.safe_attributes 'qbo_invoice_id'

View File

@@ -22,7 +22,7 @@ module IssuePatch
# Same as typing in the class
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
belongs_to :qbo_customer, primary_key: :id
belongs_to :customer, primary_key: :id
belongs_to :qbo_item, primary_key: :id
belongs_to :qbo_estimate, primary_key: :id
belongs_to :qbo_invoice, primary_key: :id

View File

@@ -16,17 +16,16 @@ class IssuesFormHookListener < Redmine::Hook::ViewListener
f = context[:form]
# Check to see if there is a quickbooks user attached to the issue
selected_customer = context[:issue].qbo_customer ? context[:issue].qbo_customer.id : nil
selected_customer = context[:issue].customer ? context[:issue].customer.id : nil
selected_item = context[:issue].qbo_item ? context[:issue].qbo_item.id : nil
selected_invoice = context[:issue].qbo_invoice ? context[:issue].qbo_invoice.id : nil
selected_estimate = context[:issue].qbo_estimate ? context[:issue].qbo_estimate.id : nil
selected_vehicle = context[:issue].vehicles_id ? context[:issue].vehicles_id : nil
customer = QboCustomer.find_by_id(selected_customer) if selected_customer
vehicle = context[:issue].vehicles_id
# Load customer information without callbacks
customer = Customer.find_by_id(selected_customer) if selected_customer
select_customer = f.select :customer_id, Customer.all.pluck(:name, :id).sort, :selected => selected_customer, include_blank: true
# Generate the drop down list of quickbooks customers
select_customer = f.select :qbo_customer_id, QboCustomer.all.pluck(:name, :id).sort, :selected => selected_customer, include_blank: true
# Generate the drop down list of quickbooks items
select_item = f.select :qbo_item_id, QboItem.all.pluck(:name, :id).sort, :selected => selected_item, include_blank: true
@@ -36,12 +35,13 @@ class IssuesFormHookListener < Redmine::Hook::ViewListener
# Generate the drop down list of quickbooks extimates
select_estimate = f.select :qbo_estimate_id, QboEstimate.all.pluck(:doc_number, :id).sort! {|x, y| y <=> x}, :selected => selected_estimate, include_blank: true
#@estimates_link = link_to qbo_update_estimates_path
if context[:issue].customer
vehicles = customer.vehicles.pluck(:name, :id).sort!
else
vehicles = Vehicle.all.order(:name).pluck(:name, :id)
end
#render_on :view_issues_form_details_bottom, :partial => 'hooks/redmine_qbo/vehicles/dropdown'
vehicles = customer.vehicles.pluck(:name, :id).sort if customer
vehicles = Vehicle.all if not vehicles
vehicle = f.select :vehicles_id, vehicles, include_blank: true, :selected => vehicle
vehicle = f.select :vehicles_id, vehicles, :selected => selected_vehicle, include_blank: true
return "<p>#{select_customer}</p> <p>#{select_item}</p> <p>#{select_invoice}</p> <p>#{select_estimate}</p> <p>#{vehicle}</p>"
end

View File

@@ -15,7 +15,7 @@ class IssuesSaveHookListener < Redmine::Hook::ViewListener
issue = context[:issue]
# Check to see if we have registered with QBO
if Qbo.first && issue.qbo_customer && issue.qbo_item
if Qbo.first && issue.customer && issue.qbo_item
# if this is a quote, lets create a new estimate based off estimated hours
if issue.tracker.name = "Quote" && issue.status.name = "New" && issue.qbo_estimate
@@ -26,7 +26,7 @@ class IssuesSaveHookListener < Redmine::Hook::ViewListener
# Create the estimate
estimate = estimate_base.qr_model(:estimate)
estimate.customer_id = issue.qbo_customer_id
estimate.customer_id = issue.customer_id
estimate.txn_date = Date.today
# Create the line item for labor
@@ -55,11 +55,14 @@ class IssuesSaveHookListener < Redmine::Hook::ViewListener
# Called After Issue Saved
def controller_issues_edit_after_save(context={})
issue = context[:issue]
employee_id = issue.assigned_to.qbo_employee_id
if issue.assigned_to
employee_id = issue.assigned_to.qbo_employee_id
# Check to see if we have registered with QBO and if the issue is closed.
# If so then we need to create a new billable time activity for the customer
bill_time(issue, employee_id) if Qbo.first && issue.qbo_customer && issue.qbo_item && employee_id && issue.status.is_closed?
# Check to see if we have registered with QBO and if the issue is closed.
# If so then we need to create a new billable time activity for the customer
bill_time(issue, employee_id) if Qbo.first && issue.customer && issue.qbo_item && employee_id && issue.status.is_closed?
end
end
# Create billable time entries
@@ -90,7 +93,7 @@ class IssuesSaveHookListener < Redmine::Hook::ViewListener
item = item_service.fetch_by_id issue.qbo_item_id
time_entry.description = "#{issue.tracker} ##{issue.id}: #{issue.subject}"
time_entry.employee_id = employee_id
time_entry.customer_id = issue.qbo_customer_id
time_entry.customer_id = issue.customer_id
time_entry.billable_status = "Billable"
time_entry.hours = hours
time_entry.minutes = minutes

View File

@@ -21,7 +21,9 @@ class IssuesShowHookListener < Redmine::Hook::ViewListener
issue = context[:issue]
# Check to see if there is a quickbooks user attached to the issue
customer = issue.qbo_customer ? issue.qbo_customer.name : nil
if issue.customer
customer = link_to issue.customer.name, "#{Redmine::Utils::relative_url_root}/customers/#{issue.customer.id}"
end
# Check to see if there is a quickbooks item attached to the issue
item = issue.qbo_item ? issue.qbo_item.name : nil
@@ -39,17 +41,19 @@ class IssuesShowHookListener < Redmine::Hook::ViewListener
end
if issue.vehicles_id
v = Vehicle.find_by_id(issue.vehicles_id)
begin
v = Vehicle.find(issue.vehicles_id)
vehicle = link_to v.to_s, "#{Redmine::Utils::relative_url_root}/vehicles/#{v.id}"
vin = v.vin
notes = v.notes
rescue
#do nothing
end
return "
<div class=\"attributes\">
<div class=\"qbo_customer_id attribute\">
<div class=\"customer_id attribute\">
<div class=\"label\"><span>Customer</span>:</div>
<div class=\"value\">#{customer}</div>
</div>
@@ -78,7 +82,7 @@ class IssuesShowHookListener < Redmine::Hook::ViewListener
<div class=\"vehicle_vin attribute\">
<div class=\"label\"><span>VIN</span>:</div>
<div class=\"value\">#{vin}</div>
<div class=\"value\">#{vin.gsub(/(.{9})/, '\1 ') if vin}</div>
</div>
<div class=\"vehicle_notes attribute\">

View File

@@ -37,10 +37,11 @@ module IssuesPdfHelperPatch
pdf.RDMMultiCell(190, 5, "#{format_time(issue.created_on)} - #{issue.author}")
pdf.ln
customer = issue.customer.name if issue.customer
left = []
left << [l(:field_status), issue.status]
left << [l(:field_priority), issue.priority]
left << [l(:field_qbo_customer), issue.qbo_customer.name]
left << [l(:field_customer), customer]
left << [l(:field_assigned_to), issue.assigned_to] unless issue.disabled_core_fields.include?('assigned_to_id')
#left << [l(:field_category), issue.category] unless issue.disabled_core_fields.include?('category_id')
#left << [l(:field_fixed_version), issue.fixed_version] unless issue.disabled_core_fields.include?('fixed_version_id')
@@ -50,8 +51,8 @@ module IssuesPdfHelperPatch
vin = v ? v.vin : nil
notes = v ? v.notes : nil
left << [l(:field_vehicles), vehicle]
left << [l(:field_vin), vin]
left << [l(:field_notes), notes]
left << [l(:field_vin), vin.gsub(/(.{9})/, '\1 ')]
#left << [l(:field_notes), notes]
right = []
right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date')
@@ -59,7 +60,7 @@ module IssuesPdfHelperPatch
right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio')
right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours')
right << [l(:label_spent_time), l_hours(issue.total_spent_hours)] if User.current.allowed_to?(:view_time_entries, issue.project)
#right << [l(:field_notes), notes]
right << [l(:field_notes), notes]
rows = left.size > right.size ? left.size : right.size
while left.size < rows

View File

@@ -35,7 +35,7 @@ module QueryPatch
def available_columns_with_qbo
unless @available_columns
@available_columns = available_columns_without_qbo
@available_columns << QueryColumn.new(:qbo_customer, :sortable => "#{QboCustomer.table_name}.name", :groupable => true, :caption => :field_qbo_customer)
@available_columns << QueryColumn.new(:customer, :sortable => "#{Customer.table_name}.name", :groupable => true, :caption => :field_customer)
end
@available_columns
end
@@ -44,11 +44,20 @@ module QueryPatch
unless @available_filters
@available_filters = available_filters_without_qbo
qbo_filters = {
"customer" => {
:name => l(:field_qbo_customer),
:type => :text,
:order => @available_filters.size + 1},
#qbo_filters = {
# :customer => {
# :id => l(:field_customer),
# :type => :integer,
# :order => @available_filters.size + 1},
#}
qbo_filters = {
"customer_id" => {
:id => :customer_id,
:type => :list_optional,
:order => @available_filters.size + 1,
#:values => Customer.find(:all).collect { |c| [c.name, c.id.to_s]}
}
}
@available_filters.merge!(qbo_filters)

View File

@@ -14,7 +14,7 @@ class UsersShowHookListener < Redmine::Hook::ViewListener
def view_users_form(context={})
# Update the users
QboEmployee.update_all
#QboEmployee.update_all
# Check to see if there is a quickbooks user attached to the issue
@selected = context[:user].qbo_employee.id if context[:user].qbo_employee