Compare commits

...

402 Commits
0.7.4 ... v0.9

Author SHA1 Message Date
Rob Harrington
312a6299a8 Making where clause unambiguous 2015-05-15 21:19:16 +10:00
Rohan Mitchell
ef064819f9 Add spec for order_cycle_management report access 2015-05-15 10:41:29 +10:00
Rohan Mitchell
924492ec5b Merge branch 'ordercyclemanagementreports2' of https://github.com/lin-d-hop/openfoodnetwork into lin-d-hop-ordercyclemanagementreports2 2015-05-15 10:37:34 +10:00
Continuous Integration
e3723da65a Auto-merge from CI [skip ci] 2015-05-14 14:32:07 +10:00
Rohan Mitchell
b4755c37dc Merge branch 'analytics' into combined/fix-delayed-job-loop-and-analytics 2015-05-14 11:03:27 +10:00
Rohan Mitchell
b86872095a Add google analytics 2015-05-13 14:52:17 +10:00
Rohan Mitchell
3520127c41 Fix infinite job loop 2015-05-13 11:06:42 +10:00
Continuous Integration
3d0880857a Auto-merge from CI [skip ci] 2015-05-08 16:24:39 +10:00
Rohan Mitchell
e8c8d8885c Merge branch 'master' into single-order-patches 2015-05-08 12:42:56 +10:00
Rohan Mitchell
6fb3fa55a1 Allow extended time for all parts of this spec to fix intermittent fails 2015-05-07 14:23:58 +10:00
Rob Harrington
f3f0766279 Adding a distributor to order cycle to fix broken feature spec 2015-05-07 12:50:57 +10:00
Rob Harrington
0d5ce5ff57 Fixing issues with reports controller spec 2015-05-07 12:50:57 +10:00
Rob Harrington
68b4cb59be Fixing bulk management specs broken by making order_cycles filter update dates 2015-05-07 12:50:57 +10:00
Rob Harrington
f88fdac710 Adding module - doh! 2015-05-07 12:50:56 +10:00
Rob Harrington
a7019e7e78 Adding permissions method for order report enterprises 2015-05-07 12:50:56 +10:00
Rob Harrington
bd66091d75 Push logic for checking of user super admin status down into private method 2015-05-07 12:50:56 +10:00
Rob Harrington
d8f5669fbb Renaming granted > related_enterprises_granted 2015-05-07 12:50:56 +10:00
Rob Harrington
5806f50a84 Renaming granting > related_enterprises_granting 2015-05-07 12:50:56 +10:00
Rob Harrington
5cd528a87d Removing obsolete related_enterprises_with permission method 2015-05-07 12:50:56 +10:00
Rob Harrington
f0f7e0ee2f Making permissions method managed_and_related_enterprise_with method more specific 2015-05-07 12:50:56 +10:00
Rob Harrington
7ffe0f042e Moving accessible_by scope on Enterprise to permissions 2015-05-07 12:50:55 +10:00
Rob Harrington
f79fba52be Hiding personal details of customers, where the user does not manage the distributor of the order or the coordinator of the order cycle 2015-05-07 12:50:55 +10:00
Rob Harrington
4259b466f5 Using new order and line item permissions to fetch items to display in Orders and Fullfillment reports 2015-05-07 12:50:55 +10:00
Rob Harrington
0a03483e36 Adding permissions methods for visible and editable orders and line_items 2015-05-07 12:50:55 +10:00
Rob Harrington
28bf7037db Updating methods for retrieving allowed producers, distributors and order cycles for order and fulfillment reports 2015-05-07 12:50:55 +10:00
Rob Harrington
ed9bbe2c45 Sorting Hub and Producer filter selectors by name 2015-05-07 12:50:55 +10:00
Rob Harrington
b5c7607d67 Order cycle filter resets date filters on BOM 2015-05-07 12:50:55 +10:00
Rob Harrington
e640376d63 Don't load cancelled orders into bulk order management 2015-05-07 12:50:54 +10:00
Rob Harrington
9ab16d8cec Allowing calls to Api::OrderCyclesController#accessible to specify :as => 'distributor' or 'producer' 2015-05-07 12:50:54 +10:00
Rob Harrington
d8c23d37ac Update accessible_by scope on enterprise, to read from permissions 2015-05-07 12:50:54 +10:00
Rob Harrington
89b153dc2c Update AJAX request to use sells instead of deprecated is_distributor attribute 2015-05-07 12:50:54 +10:00
Rohan Mitchell
bd6bac8874 Display deployment output in real time
This reverts commit 485eee4bdd.
2015-05-06 20:02:22 +10:00
Rohan Mitchell
50d2ddc05f Add progress comments 2015-05-06 20:00:50 +10:00
Rohan Mitchell
10b7a86745 Add debugging to merge script 2015-05-06 19:50:06 +10:00
Rohan Mitchell
6d33dc5070 Add script to merge master into the current branch if required before running specs 2015-05-06 19:41:36 +10:00
Rohan Mitchell
d109e898d2 Preserve newlines when displaying deploy script output 2015-05-06 19:38:20 +10:00
Rohan Mitchell
3dee29cd12 Remove build badge - master branch is always green 2015-05-06 19:37:21 +10:00
Rohan Mitchell
0921cd2dfa Merge branch 'master' into single-order-patches 2015-05-06 18:13:55 +10:00
Rohan Mitchell
7b4130972b Fix first feature spec sometimes timing out 2015-05-06 18:12:17 +10:00
Rohan Mitchell
485eee4bdd Deploy scripts display their output 2015-05-06 18:07:50 +10:00
Rohan Mitchell
f84e704d99 Retry simple push-to-master script 2015-05-06 17:59:36 +10:00
Rohan Mitchell
ad7e5a45bb Add updated merge script 2015-05-06 17:58:36 +10:00
Rohan Mitchell
d9404d3332 Merge branch 'master' into single-order-patches 2015-05-06 17:29:23 +10:00
Rohan Mitchell
e43d726b97 Merge branch 'master' into payments-report-fix 2015-05-06 14:55:10 +10:00
Rob Harrington
8788322492 Alllowing payments in payment reports to access soft-deleted payment methods 2015-05-06 11:10:50 +10:00
Rick Giner
368402f115 Changed selectors' ng-repeat. Using existing variable instead of method call 2015-05-03 15:24:16 +10:00
Rick Giner
9e70c80d1d bind-once in product modal 2015-05-03 14:48:27 +10:00
Rick Giner
8fb11defdb bind-once in groups home page 2015-05-03 14:41:34 +10:00
Rick Giner
9c26b3ebb2 bind-once in partials 2015-05-03 14:34:42 +10:00
Rick Giner
3fc616cdff bind-once on hubs 2015-05-03 14:11:09 +10:00
Rick Giner
16e9f0545b bind-once in products 2015-05-03 14:02:33 +10:00
Rick Giner
a3664d4448 Added bindonce and ng-if improvements to Producers templates 2015-05-03 12:51:59 +10:00
Maikel Linke
11acb3ba59 Allow to remove adjustments
Managers of an order cycle and the distributor of an order are allowed
to remove an adjustment from the order.
2015-05-01 15:59:46 +10:00
Rohan Mitchell
e91de69d5a Merge branch 'master' into pin-refunds 2015-05-01 14:58:19 +10:00
Rohan Mitchell
03ae740cd6 Revert "Display header for Xero invoices report"
This reverts commit a6cecdcc25.
2015-05-01 14:55:26 +10:00
Maikel Linke
7c55285708 Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into single-order-patches 2015-05-01 14:50:51 +10:00
Maikel Linke
e6e063670c Allow managers to remove line items from order
Managers of an order cycle and the distributor of an order are allowed to
remove a line item from the order.
2015-05-01 14:49:34 +10:00
Rohan Mitchell
153604dd64 Merge branch 'single-order-patches' 2015-05-01 14:39:17 +10:00
Maikel Linke
b7bac326bd admin order edit: re-label update button to "update and recalculate fees" 2015-05-01 12:05:43 +10:00
Rohan Mitchell
a6cecdcc25 Display header for Xero invoices report 2015-05-01 11:59:52 +10:00
Maikel Linke
af78859db6 Merge remote-tracking branch 'origin/master' into single-order-patches 2015-04-30 17:18:02 +10:00
Maikel Linke
5efc0a5110 quick fix: update fees after updating order 2015-04-30 16:29:51 +10:00
Rohan Mitchell
2c7a5c0656 Update Spree - fixes bug where Payment#method_missing depends on #provider already called. 2015-04-30 15:49:48 +10:00
Rohan Mitchell
0b652a2113 Add refund icon 2015-04-30 15:49:48 +10:00
Rohan Mitchell
b498c28632 Payments can be refunded 2015-04-30 15:49:48 +10:00
Rohan Mitchell
8184a7c7b2 Pin payments can't void or credit, but they can refund 2015-04-30 15:49:48 +10:00
Rohan Mitchell
b09ae550c8 Add spec for payment actions 2015-04-30 15:49:48 +10:00
Rohan Mitchell
f4df227ef0 Buildkite should now support Fuubar 2015-04-30 13:54:27 +10:00
Rohan Mitchell
a207f50aeb Merge branch 'master' into delay-devise-emails
Conflicts:
	script/run_tests.sh
2015-04-30 12:29:06 +10:00
Maikel Linke
ecf635e080 handle missing bill_address on admin order page 2015-04-29 14:32:13 +10:00
Maikel Linke
2e66a082eb add customer notes to admin order index page 2015-04-29 14:31:59 +10:00
Rohan Mitchell
3b61d7a1e0 Add ref for country ISO codoes 2015-04-29 14:12:08 +10:00
Rohan Mitchell
c3f99d7540 Merge branch '441-default-country' of https://github.com/folklabs/openfoodnetwork into folklabs-441-default-country 2015-04-29 14:07:58 +10:00
Maikel Linke
f6d87eee87 Merge remote-tracking branch 'origin/master' into single-order-patches 2015-04-29 13:20:44 +10:00
Maikel Linke
e82a3a9d82 add ship button to admin order index page 2015-04-29 12:30:05 +10:00
Maikel Linke
8511bd19ce add ship button to order edit page 2015-04-29 12:03:49 +10:00
Maikel Linke
1268108877 handle ship event on order 2015-04-29 12:03:11 +10:00
Maikel Linke
2b0f867ed8 new order method ready_to_ship? 2015-04-29 11:42:35 +10:00
Lynne Davis
9e61a7d083 Adding report type drop down to order_cycle_management_report 2015-04-26 11:03:32 +01:00
Lynne Davis
6bbd3f7c13 Added auth for order_cycle_management_report. This report was breaking supplier enterprises reports due to incorrect authorization. 2015-04-26 11:02:06 +01:00
Rob Harrington
6a4de7c7e2 Hiding filters on list views because styling is broken 2015-04-24 19:35:18 +10:00
Rob Harrington
505fd8ff96 Merge branch 'properties' of github.com:openfoodfoundation/openfoodnetwork into properties 2015-04-24 17:20:41 +10:00
Rob Harrington
b1b1bfd8f6 Resolve conflict for overflow dropdown between multiple single-line-selectors on the one page 2015-04-24 16:05:39 +10:00
Maikel Linke
f94a5a975a Edit Order: resend button uses new pretty template. 2015-04-24 15:31:45 +10:00
Rohan Mitchell
29faa5f3c6 Merge branch 'master' into properties 2015-04-24 15:14:52 +10:00
Rohan Mitchell
8e2c224d4d cd before sourcing includes 2015-04-24 15:00:49 +10:00
Rohan Mitchell
bb2f2a6f54 Also stop delayed job before loading staging baseline 2015-04-24 15:00:38 +10:00
Rob Harrington
dab3b59f6a Merge branch 'master' into properties 2015-04-24 14:00:08 +10:00
Rob Harrington
bdf462926d Ensure that producer properties have a position 2015-04-24 13:05:01 +10:00
Maikel Linke
355221a273 Adding customer name to order edit page heading 2015-04-24 12:33:25 +10:00
Rohan Mitchell
9149276048 Kill any postgres connections before dropping and recreating database 2015-04-24 12:17:39 +10:00
Rob Harrington
c66a7e44b6 Updating product model specs to reflect changes to properties 2015-04-23 15:37:41 +10:00
Rob Harrington
9eb99d1c4a Merge branch 'master' into properties 2015-04-23 14:18:30 +10:00
Rob Harrington
6cde1f7732 Add tooltip with value for selectors 2015-04-23 14:11:50 +10:00
Rob Harrington
7b83438b5e Pulling property values into the shopfront 2015-04-23 13:51:49 +10:00
Rob Harrington
e6a98747b4 correction in read only logic for filter selectors 2015-04-23 13:32:56 +10:00
Rob Harrington
ed15b95de0 Adding properties and taxons to producer modal 2015-04-23 12:31:20 +10:00
Rob Harrington
3df2720b31 Making filter selectors more flexible, allowing no active-selectors to be passed in, ie. read-only 2015-04-23 12:31:06 +10:00
Maikel Linke
eff8681d9b Merge branch 'master' into single-order-patches 2015-04-23 12:11:44 +10:00
Maikel Linke
a937fd3c61 Using variant overrides in variant seach on order edit page 2015-04-23 11:37:10 +10:00
Maikel Linke
3412bc25bf Edit Orders: more variant info in variant search
Displaying variant's full name and the producer's name.
2015-04-23 10:17:01 +10:00
Maikel Linke
f1a8011e13 Documentation of Variant.full_name
The code was confusing for all developers here. Maybe a bit of doco
helps.
2015-04-23 10:02:32 +10:00
Rohan Mitchell
92e03e208f Extract load_environment method 2015-04-23 07:23:34 +10:00
Rob Harrington
0251d8962d Adding sku to BPE 2015-04-22 21:02:07 +10:00
Rob Harrington
1c617994fc User can toggle property inheritence from product property page, and checking the box shows a list of producer properties that will be inherited from 2015-04-22 21:02:07 +10:00
Rob Harrington
4a4b3da551 Using properties_including_inherited for product properties on the shop page 2015-04-22 21:02:07 +10:00
Rob Harrington
e546388784 Rename properties_h to properties_including_inherited 2015-04-22 21:02:07 +10:00
Rob Harrington
976c24cf4c properties_h uses inherit_properties flag, and returns property id rather than presentation 2015-04-22 21:02:07 +10:00
Rob Harrington
f610a709e1 Adding inherits_properties to BPE 2015-04-22 21:02:06 +10:00
Rob Harrington
5d6f265c0a Moving spree namespaced serializers into admin 2015-04-22 21:02:06 +10:00
Rob Harrington
1f293bb787 Adding inherits properties flag to products 2015-04-22 21:02:06 +10:00
Rob Harrington
a4a41ae26a Refactor properties_h 2015-04-22 21:02:06 +10:00
Rohan Mitchell
7aeeb6d18f Add script to run JS specs in CI 2015-04-22 16:36:31 +10:00
Rohan Mitchell
7a78f4870a Use phantomjs for js specs, so we can run them in CI 2015-04-22 16:33:44 +10:00
Rohan Mitchell
28c79cdb50 Use db:test:load instead of db:test:prepare in CI to avoid conflicts between branches 2015-04-22 15:01:22 +10:00
Rohan Mitchell
b9e3ff54b8 Add build script to merge to master 2015-04-22 14:47:54 +10:00
Rohan Mitchell
0c0be0112e Update paths to include ci 2015-04-22 14:31:30 +10:00
Rohan Mitchell
883a2e0a0e WIP: Move CI scripts to their own folder 2015-04-22 14:29:59 +10:00
Rohan Mitchell
6c81109b17 Local branch isn't checked out, so we need to test remote branch 2015-04-22 14:17:07 +10:00
Rohan Mitchell
1c9a95b3d6 Set execute bit 2015-04-22 13:19:17 +10:00
Rohan Mitchell
53c4c8b5b7 Push to staging fails unless master has been merged into current branch 2015-04-22 13:16:39 +10:00
Rohan Mitchell
d406f9ccdf Tests fail unless master has been merged into current branch 2015-04-22 13:14:51 +10:00
Rohan Mitchell
7d4a4f8f9d Pushing to staging first loads staging baseline data 2015-04-22 12:55:36 +10:00
Rohan Mitchell
35536a629c Set execute bit 2015-04-22 12:55:36 +10:00
Rohan Mitchell
7b8938b5f6 Run password reset job for spec that requires it 2015-04-22 07:32:22 +10:00
Rohan Mitchell
b2717ffca0 Use db:test:load instead of db:test:prepare in CI to avoid conflicts between branches 2015-04-21 16:40:45 +10:00
Rohan Mitchell
700cb73b8f Send enterprise confirmation emails asynchronously 2015-04-21 16:19:02 +10:00
Rohan Mitchell
9d225142c8 Send password reset instructions asynchronously 2015-04-21 16:10:40 +10:00
Rohan Mitchell
998288e21f Keep failed jobs around for debugging. Limit max runtime to 15 mins (we're only sending emails at present). Notify bugsnag of errors in jobs. 2015-04-21 15:37:36 +10:00
Rohan Mitchell
9f93c9f221 Swap Jenkins build badge out for Buildkite 2015-04-21 15:17:34 +10:00
Rohan Mitchell
22127b2d18 Use progress formatter for less verbose CI output. I miss Fuubar formatter, though. 2015-04-21 15:17:34 +10:00
Rohan Mitchell
692e58e8f7 Output spec-by-spec results to track specs-hanging-at-90-percent issue 2015-04-21 10:52:14 +10:00
Rohan Mitchell
4158663e9a Pushing to production saves staging baseline data 2015-04-21 10:47:36 +10:00
Rohan Mitchell
a1673afff0 Allow more time for phantomjs, required by first admin spec where assets are compiled 2015-04-17 15:46:51 +10:00
Rohan Mitchell
0d4dbd23fd Remove redundant spec line, test that sells is not changed 2015-04-17 15:42:42 +10:00
Rohan Mitchell
0d9ba4257d Merge branch 'properties' 2015-04-17 15:25:51 +10:00
Rob Harrington
c43eb9ef72 Merge branch 'email_user' into properties 2015-04-17 15:17:37 +10:00
Rob Harrington
46690faffb Fixing Darkswarm Angular Product Controller spec 2015-04-17 15:14:19 +10:00
Rob Harrington
32f14bca00 Preventing fitting of selectors when there are none 2015-04-17 15:10:41 +10:00
Rohan Mitchell
042e076b58 Fix tax-related spec failures 2015-04-17 14:46:32 +10:00
Rob Harrington
6d96a7a60b Specifiy that allSelectors attribute on filterSelectors directive is optional 2015-04-17 14:43:09 +10:00
Rob Harrington
c8bf207187 Fixing trial expiry test 2015-04-17 14:33:47 +10:00
Rohan Mitchell
9e8483348f Fix spec - enterprise needs to charge sales tax for tax to be charged 2015-04-17 13:41:38 +10:00
Rohan Mitchell
81324f3cc4 Do not charge tax on shipments when distributor does not charge sales tax 2015-04-17 13:41:38 +10:00
Rohan Mitchell
0b8a619274 When the order does not have a hub, all tax rates apply 2015-04-17 13:41:38 +10:00
Rohan Mitchell
048c6a8ee8 Include only the bare minimum of helpers into JS template context to avoid intermittent SASS @include issues 2015-04-17 13:41:38 +10:00
Rohan Mitchell
3e8801b12b Do not charge sales tax on items or on enterprise fees when the distributor of the order does not charge sales tax 2015-04-17 13:41:38 +10:00
Rohan Mitchell
a6a5fdfb3b Require that the user selects whether their enterprise charges sales tax 2015-04-17 13:41:38 +10:00
Rohan Mitchell
0bdb8f7241 User can set whether an enterprise charges sales tax when registering 2015-04-17 13:41:38 +10:00
Rohan Mitchell
05551aa2a9 Make helpers available to javascript templates 2015-04-17 13:41:38 +10:00
Rohan Mitchell
9bbc151cae Admin can set enterprises to charge or not charge sales tax 2015-04-17 13:41:38 +10:00
Rohan Mitchell
08fef890ec Do not show tax lines if there is no tax on the order 2015-04-17 13:41:14 +10:00
Rohan Mitchell
a93633a626 Show tax on order confirmation emails 2015-04-17 13:41:14 +10:00
Rohan Mitchell
4bd1ff2011 Extract the bulk of the confirmation emails into partials, eliminating a lot of duplication 2015-04-17 13:40:08 +10:00
Rohan Mitchell
2914990444 Add save_and_open spec helper method to open HTML emails in the browser 2015-04-17 13:40:08 +10:00
Rohan Mitchell
3ce2c5b84f Show tax on order confirmation page 2015-04-17 13:40:08 +10:00
Rohan Mitchell
77d7255243 Use short syntax for rendering partials 2015-04-17 13:39:10 +10:00
Rohan Mitchell
6bb926f811 Do not show tax in checkout 2015-04-17 13:39:09 +10:00
Rohan Mitchell
829d11d4b2 Deliver a warning if attempting to create an invalid taxed_product from factory 2015-04-17 13:39:09 +10:00
Rohan Mitchell
beec910445 Display tax in cart 2015-04-17 13:39:09 +10:00
Rohan Mitchell
68f0e51c02 Change add_product_to_cart spec helper to use OrderPopulator, reducing inconsistencies in order adjustments, tax etc. 2015-04-17 13:39:09 +10:00
Rohan Mitchell
210c76eddc Checkout won't load without payment and shipping methods; move spec to context where it can test the checkout 2015-04-17 13:39:09 +10:00
Rohan Mitchell
e75c6a8e1d Add helper to display total tax on an order 2015-04-17 13:39:09 +10:00
Rob Harrington
b44f2bcdf5 Fixing trial expiry test 2015-04-17 13:30:36 +10:00
Rob Harrington
f13b52411d Merge branch master into properties 2015-04-17 13:23:33 +10:00
Rob Harrington
0cf8b017b9 Pulling out taxons and properties placeholders from producer and product modals 2015-04-17 13:20:01 +10:00
Rohan Mitchell
2b5fc656fe Configure delayed job logging, add startup script for monit 2015-04-17 10:40:25 +10:00
Rob Harrington
524f02717b Don't redirect to root when closing login window on checkout page 2015-04-17 10:25:38 +10:00
Rob Harrington
456a6f94f5 On enterprise confirmation: create a new user based on enterprise contact email if one does not already exist, and add it as a manager 2015-04-17 10:24:37 +10:00
Rob Harrington
afe77925ba Allow request to specify a return value when calling user_passwords#edit 2015-04-17 10:21:25 +10:00
Rob Harrington
5940ff2b2c Don't override devise's after_sign_in_path_for, use specific before filters for user sessions and registrations controllers instead 2015-04-16 16:56:27 +10:00
Rohan Mitchell
d1ab2d9dac Add daemons gem for Delayed::Job 2015-04-16 16:54:43 +10:00
Rohan Mitchell
ccc1f3df40 Feature specs test email sending through delayed jobs 2015-04-16 16:54:43 +10:00
Rohan Mitchell
e9fbd74e88 Send emails via jobs instead of synchronously 2015-04-16 16:54:43 +10:00
Rohan Mitchell
bb3bdf37cd Add jobs for user, order and enterprise emails 2015-04-16 16:54:43 +10:00
Rohan Mitchell
af4baabb50 Include DelayedJobHelper for specs 2015-04-16 16:54:43 +10:00
Rohan Mitchell
3bbf42c3e7 WIP: Rename delayed job support to delayed job helper 2015-04-16 16:54:43 +10:00
Rohan Mitchell
530740158c Tolerate no jobs previously in queue 2015-04-16 16:54:43 +10:00
Rohan Mitchell
771b9e0df5 Improve syntax: take job class as a separate argument 2015-04-16 16:54:43 +10:00
Rohan Mitchell
1d5a4c93e4 Add delayed job testing support, original credit Mat Holroyd and Rohan Mitchell, from CERES Fairfood project 2015-04-16 16:54:43 +10:00
Rohan Mitchell
61cb2514cd Add Delayed::Job 2015-04-16 16:54:43 +10:00
Rohan Mitchell
aef3fdf4b4 Merge branch 'group-pages' 2015-04-16 16:53:49 +10:00
Rohan Mitchell
a384f5e3d4 Merge branch 'buildkite' into customer-totals-report-and-perms-fix 2015-04-16 14:08:39 +10:00
Rohan Mitchell
318957551f Freeze time to make spec repeatable 2015-04-16 14:07:38 +10:00
Rohan Mitchell
e017c30ab7 Do not double-run db:test:prepare 2015-04-16 14:07:37 +10:00
Rohan Mitchell
23888b7576 chmod +x 2015-04-16 14:07:37 +10:00
Rohan Mitchell
ff07707af7 Symlink it right 2015-04-16 14:07:37 +10:00
Rohan Mitchell
78bf87614a Buildkite: Symlink config/application.yml if not present 2015-04-16 14:07:37 +10:00
Rohan Mitchell
2b50f993de Load environment before attempting build 2015-04-16 14:07:37 +10:00
Rohan Mitchell
4672cc4863 Add buildkite scripts 2015-04-16 14:07:37 +10:00
Rohan Mitchell
768cfab591 Change field text at checkout 2015-04-16 10:59:15 +10:00
Rohan Mitchell
7f973604e5 Add columns to customer totals report: order cycle, payment method, customer code, tags, billing address 2015-04-16 10:59:15 +10:00
Rohan Mitchell
7f6c02ca29 Add User#customer_of to look up customers 2015-04-16 10:59:15 +10:00
Rohan Mitchell
34d1841d22 Make Variant#full_name resilient to regex chars 2015-04-16 10:59:15 +10:00
Rohan Mitchell
e570352a1b Grant fewer permissions on enterprise creation 2015-04-16 10:59:15 +10:00
Rohan Mitchell
2e021941d1 Fix bug where new enterprises should be created as hubs, but aren't 2015-04-16 10:59:15 +10:00
Rohan Mitchell
48bf87ec73 Perpetually updating copyright year 2015-04-16 10:59:15 +10:00
Maikel Linke
548e3576b9 textAngular editor for group description 2015-04-15 17:13:10 +10:00
Maikel Linke
201bcb133a show profiles checkbox on groups hubs page 2015-04-15 16:15:21 +10:00
Rob Harrington
0c155e6e3a Display message when email has not been confirmed for new enterprise 2015-04-15 15:32:17 +10:00
Rob Harrington
2072744870 User can enter the number of months back to search for order cycles from which to build relationships 2015-04-12 11:38:18 +10:00
Rob Harrington
0f9fbe6e8c Preventing relationships from being created with self 2015-04-12 10:53:22 +10:00
Rob Harrington
b24cad7aeb Providing access to order_cycle_permissions in order cycles controller 2015-04-11 23:25:30 +10:00
Rob Harrington
bc89018ee1 Refer to the right variable doofus 2015-04-11 23:24:50 +10:00
Rob Harrington
88bae32971 Adding method: user_manages_coordinator_or(enterprise) to make code a bit more terse 2015-04-11 23:00:34 +10:00
Rob Harrington
6f81a9ba18 Save common permission method results as instance variables 2015-04-11 22:53:57 +10:00
Rob Harrington
22a37cdc8a Rename managed_producers_in as managed_participating_producers 2015-04-11 22:44:32 +10:00
Rob Harrington
9c376f0b00 Rename managed_hubs_in as managed_participating_hubs 2015-04-11 22:32:15 +10:00
Rob Harrington
59a2c84857 Rename managed_enterprises_in as managed_participating_enterprises 2015-04-11 22:30:21 +10:00
Rob Harrington
6ac45f3dc8 Renaming order_cycle_exchanges as visible_exchanges 2015-04-11 22:26:55 +10:00
Rob Harrington
e3138c3cd2 Renaming order_cycle_enterprises_for as visible_enterprises 2015-04-11 22:25:23 +10:00
Rob Harrington
26d55baa35 Moving order cycle permissions to their own permissions class 2015-04-11 21:11:10 +10:00
Rob Harrington
02f8f293da Only allow managers or coordinator to add/remove fees from exchanges 2015-04-11 18:32:04 +10:00
Maikel Linke
2fd25f6cc4 Injecting all enterprises into group page
The enterprises have related producers and hubs that need to be
dereferenced. Therefore, we need a bigger set of enterprises to be
loaded. Injecting all enterprises is simple and doesn't require changes
if the set of needed enterprise data is growing in future.
2015-04-10 17:42:54 +10:00
Rob Harrington
24e3c9a9e1 Adding bugsnag notify block for catching naughty phantom fees 2015-04-10 16:41:10 +10:00
Rob Harrington
8b7d321dfe Changing delete time to ensure not_deleted scope works 2015-04-10 16:40:33 +10:00
Rob Harrington
72403fd021 Fixing broken enterprise controller spec 2015-04-10 13:16:21 +10:00
Maikel Linke
1e168afd71 giving the enterprise serializer the active_distributors 2015-04-10 12:55:20 +10:00
Rob Harrington
1e6fd94663 Adding rake task to create E2E relationships with P-OC based on past order_cycles 2015-04-10 12:51:15 +10:00
Rob Harrington
96c173414b Adding has_permission method to enterprise_relationship 2015-04-10 12:48:27 +10:00
Rob Harrington
226e2f0e2c Fixing error caused by order show template doing a lookup based on current distributor rather than order distributor 2015-04-10 09:26:20 +10:00
Rob Harrington
2280a71b23 Replace for_order_cycle rabl template with a serializer 2015-04-10 09:25:40 +10:00
Rob Harrington
6f24e969ce Removing stupid unusable spec 2015-04-09 17:20:31 +10:00
Maikel Linke
e26ebf4239 Serialize only activated hubs and producers of an enterprise 2015-04-09 17:15:57 +10:00
Rob Harrington
81a745420e Only check editable status of variants when actually selecting 2015-04-09 15:24:45 +10:00
Rob Harrington
c28ebf63ab As participating Hub, I cannot edit incoming exchanges despite being granted P-OC by the producer 2015-04-09 13:41:43 +10:00
Rob Harrington
69004ac477 Select all box only selects variants I have permission to edit 2015-04-09 13:29:25 +10:00
Rob Harrington
430320e3f9 Oopsie! 2015-04-09 13:28:41 +10:00
Rob Harrington
60a3d8e0d1 Restrict bulk updating order cycles at controller level 2015-04-09 12:27:43 +10:00
Rob Harrington
8a3126f117 Using helper to disable form elements on order cycle index page 2015-04-09 11:11:46 +10:00
Rob Harrington
c7157ce7bd Applying new helper to order cycle name and timing partial 2015-04-09 11:11:06 +10:00
Rob Harrington
133f7e4ec7 Add viewing_as_coodinator_of? helper method 2015-04-09 11:10:56 +10:00
Rob Harrington
fbcfe9b2a4 Add viewing_as_coordiantor flag to serialized order cycles and a managed flag to serialized enterprises for_order_cycle(s) 2015-04-09 10:31:17 +10:00
Rob Harrington
adc1b639bc Merge remote-tracking branch 'origin/master' into complex_oc 2015-04-08 14:38:27 +10:00
Rob Harrington
61a9e2f7cc Add a referer for all admin enterprise controller specs 2015-04-08 14:36:56 +10:00
Rob Harrington
f6e635466b Rearranging elements on the order cycle form a little bit 2015-04-08 14:31:18 +10:00
Rob Harrington
32cc17745a Non-coordinating user cannot alter important attributes of order cycle 2015-04-08 14:12:49 +10:00
Rob Harrington
b1624a733e Editable variants for incoming exchanges for hubs include those for producers that have granted my hub P-OC 2015-04-08 13:38:37 +10:00
Rob Harrington
b8ce6ed0fc Coordinator can see any enterprises that are already in the order cycle 2015-04-08 13:28:49 +10:00
Rob Harrington
104a8ddecf Refactor order_cycle_enterpises_for permission method, now requires an order cycle 2015-04-08 13:00:17 +10:00
Rob Harrington
4dcfec1de9 make enterprises_for_order_cycle permissions more correct 2015-04-08 12:12:02 +10:00
Rob Harrington
8859aa27ee Slight refactor of order cycle enterprises 2015-04-08 10:33:32 +10:00
Rob Harrington
24062e5585 Adding permissions for outgoing hubs to see producers whose variants they are distributing, despite P-OC not existing 2015-04-08 10:15:50 +10:00
Rob Harrington
4a87798bb4 Variants belonging to a producer I manager that are already in an outgoing an exchange need not be editable 2015-04-06 23:30:43 +10:00
Rob Harrington
ae1681b790 Not 1! Zero! 2015-04-06 23:29:15 +10:00
Rob Harrington
36c5cdf556 Only show enterprises with fees in order cycle edit page 2015-04-06 14:08:10 +10:00
Rob Harrington
d516795774 Fetching Enterprise Fees for order cycle, using new enterprisefee serializer 2015-04-06 13:06:21 +10:00
Rob Harrington
7eb735f87e Adding for_enterprises scope on enterprise fee 2015-04-06 10:24:40 +10:00
Rob Harrington
7448d41b27 Adding abilities for new for_order_cycle action 2015-04-06 10:23:39 +10:00
Rob Harrington
7ebea23fda Adding route for now for_order_cycle action on enterprise fees 2015-04-06 10:23:08 +10:00
Rob Harrington
b7de8353bc Renaming existing enterprise fee serializer as basic... 2015-04-06 09:47:37 +10:00
Rob Harrington
52dc313e70 Implementing editable variant scopes in order_cycle_applicator 2015-04-06 09:20:39 +10:00
Rob Harrington
a4b80b1f33 Implement editable scope for variants on order cycles page 2015-04-06 09:15:14 +10:00
Rob Harrington
f20844c2a0 Adding editable scope for variants in outgoing exchanges 2015-04-05 15:25:44 +10:00
Rob Harrington
136d361134 Fixing comment 2015-04-05 14:14:47 +10:00
Rob Harrington
009b25a491 Adding an editable variants scope for incoming exchanges 2015-04-05 13:59:00 +10:00
Rob Harrington
bf87394a76 Fixing order cycle feature spec 2015-04-05 10:58:06 +10:00
Rob Harrington
d28fc7e42d Hubs can see incoming exchanges of producers who have given them P-OC or whose variants they are actively distributing 2015-04-03 14:58:01 +11:00
Rob Harrington
a10de68430 only load permissions once in serializer 2015-04-02 15:55:03 +11:00
Rob Harrington
3b9824171a Adding with_order_cycles_as_supplier_outer scope to Enterprise 2015-04-02 15:53:32 +11:00
Rob Harrington
5d7659aa3c Fixing product spec, using have_select2 instead of have_field 2015-04-02 14:36:19 +11:00
Rob Harrington
1e1d52cc47 Adding 'selected' option to have_select2 matcher 2015-04-02 14:35:39 +11:00
Rob Harrington
76648b97b0 Update spec, properties must exist for enterprise users before they can be assigned 2015-04-02 14:15:00 +11:00
Rob Harrington
5020eb4e32 And again: override redirect to index page when editing properties from edit page 2015-04-02 14:14:16 +11:00
Rob Harrington
cb376602f2 Override redirect to index page when editing properties from edit page 2015-04-02 14:03:51 +11:00
Rob Harrington
3aa5f6e023 Adding properties tab to admin enterprise edit form 2015-04-02 11:30:32 +11:00
Rob Harrington
8926e3765e Replace free text with with select dropdown for product property names when not super admin 2015-04-02 08:57:15 +11:00
Rob Harrington
5b235f356e Replace free text with with select dropdown for property names when not super admin 2015-04-02 08:56:36 +11:00
Rob Harrington
8ed6653dc4 Ignoring any new product properties submitted by a non-admin user 2015-04-02 08:55:20 +11:00
Rob Harrington
ca1a5b5f8d Ignoring any new producer properties submitted by the user 2015-04-02 08:54:35 +11:00
Rob Harrington
8d95ba2c69 Display full name of variant on order cycle edit form 2015-04-01 15:46:19 +11:00
Rob Harrington
94a88278a9 Ignore the unit_to_display when it is wholly contained within display_name or vice versa 2015-04-01 15:46:11 +11:00
Rob Harrington
588e036c1d Adding SKU to customer totals report 2015-04-01 14:45:23 +11:00
Rob Harrington
aa7ddbcba4 Renaming Dist. column to Admin & Handling 2015-04-01 14:38:15 +11:00
Rob Harrington
54af6886c2 Line items with a quantity of zero return price_with_adjustments of 0.0 2015-04-01 12:34:22 +11:00
Rob Harrington
d49dd62124 Replace unused bugsnag notification with one to test for line items with a quantity of zero 2015-04-01 11:38:06 +11:00
Paul Mackay
d4cf44a6dd Use COUNTRY_CODE instead of COUNTRY in application.yml. 2015-03-29 17:06:05 +01:00
Rob Harrington
6e77a5eebc Using the correct method name duh 2015-03-27 16:47:12 +11:00
Rob Harrington
2d5118290b Fixing broken order cycle feature specs 2015-03-27 16:19:52 +11:00
Rob Harrington
74b7feda53 coordinator of a simple order cycle has permission to add their own variants to outgoing exchanges 2015-03-27 16:16:13 +11:00
Rob Harrington
f5bacf71b7 Permissions for OrderCycleFormApplicator are determined internally 2015-03-27 16:16:13 +11:00
Rob Harrington
3817ef202c Enterprises in simple OC create controller only load after OC initialises 2015-03-27 16:16:12 +11:00
Rob Harrington
aa170ef5f6 Order cycle simple create controller uses 'new' method on OC service to initialise 2015-03-27 16:16:12 +11:00
Rob Harrington
4d14acb64d Don't send non-attributes of js order_cycle object to server 2015-03-27 16:16:12 +11:00
Rob Harrington
43d2eb4d22 Adding 'new' method to admin order cycle service, for loading data from serializer for new OCs 2015-03-27 16:16:12 +11:00
Rob Harrington
887579ecb8 Use managed_by scope on Enterprise instead of user.enterprises 2015-03-27 16:16:12 +11:00
Rob Harrington
9430999540 Filtering exchange variants, for outgoing exchange variant count 2015-03-27 16:16:12 +11:00
Rob Harrington
193a061c44 Order cycle form applicator only updates visible variants, should add an 'editable variants' scope to permissions 2015-03-27 16:16:11 +11:00
Rob Harrington
540ac845da Fixing broken js spec 2015-03-27 16:16:11 +11:00
Rob Harrington
5e015f0611 Rename visibleVariants filter to visibleProductVariants 2015-03-27 16:16:11 +11:00
Rob Harrington
681dada5df Simple OC form loads coordinator into JS 2015-03-27 16:16:11 +11:00
Rob Harrington
99bd6244ed Filtering the list of variants visible within each exchange based on permissions 2015-03-27 16:16:11 +11:00
Rob Harrington
63e345f819 Exchange serializer cuts down list of variants visible to the current user, based on permissions 2015-03-27 16:16:11 +11:00
Rob Harrington
524645aff4 Replacing visible_variants_for(exchange) with more general methods for determining visbility based on the enterprises involced and the current order cyclegs 2015-03-27 16:16:11 +11:00
Rob Harrington
d115ef5f7e Scoping old generalised order cycle helper methods to a specific order cycle 2015-03-27 16:16:10 +11:00
Rob Harrington
35b27fcfd2 Delegating responsibility for returning an empty scope when no options are passed to order_cycle_enterprises_for 2015-03-27 16:16:10 +11:00
Rob Harrington
b747f61eb1 P-OC permissions don't apply when determining which enterprises are loaded for order cycle interface 2015-03-27 16:16:10 +11:00
Rob Harrington
45f6042d3d Enterprises etched by for_order_cycle action now use permissions scoped using an order cycle or coordinator 2015-03-27 16:16:10 +11:00
Rob Harrington
a1aa9512a8 Fixing angular order_cycle controller spec 2015-03-27 16:16:10 +11:00
Rob Harrington
7e24e6743e enterprises_for is now order_cycle_enterprises_for, and can be passed an order_cycle or a coordinator (for new order_cycles) 2015-03-27 16:16:09 +11:00
Rob Harrington
c9f343f680 Swapping over scoping method for displayed enterprises in OC index page from order_cycle_enterprises to enterprises_for(order_cycle) 2015-03-27 16:15:28 +11:00
Rob Harrington
d8c4e292c8 Adding method for determining variant override hubs 2015-03-27 16:09:45 +11:00
Rob Harrington
81765de7a7 Building a permission method to determine which enterprises are visible to the user for a given OC 2015-03-27 16:07:38 +11:00
Rob Harrington
4dff3fe79c Removing unused distributable action from products api 2015-03-27 16:07:38 +11:00
Rob Harrington
1927bc55d0 Load actual variants in the exchange, wrong behaviour was implemented in previous two commits 2015-03-27 16:07:38 +11:00
Rob Harrington
e9f2e743ce Replacing old representative template for OCs with active model serializers 2015-03-27 16:07:38 +11:00
Rob Harrington
1c09b8b76f Limiting variants loaded into representative template to those a visible to the current user 2015-03-27 16:07:38 +11:00
Rob Harrington
00821a60cc More specific references to enterprise id in permissions querying methods 2015-03-27 16:07:37 +11:00
Rob Harrington
252ddf9beb Adding method to permissions library for scoping the list of visible variants in a given exchange to a particular user 2015-03-27 16:07:37 +11:00
Rob Harrington
22161bfd6e rewriting permissions query functions in permissions library, to make scoping easier 2015-03-27 16:07:37 +11:00
Rob Harrington
6c4db7fc22 Adding permission to view outgoing exchanges to producers who have granted P-OC to the relevant outgoing hub 2015-03-27 16:07:37 +11:00
Rob Harrington
df4437ecfe Altering permissions for exchanges, so the exchange is visible to managers of at least one of the enterprises invloved 2015-03-27 16:07:37 +11:00
Rob Harrington
2310a6a7db Splitting out order cycle abilities from general order management abilities 2015-03-27 16:07:37 +11:00
Rob Harrington
85e4b3970c Adding an 'involved' scope to exchanges 2015-03-27 15:56:07 +11:00
Rob Harrington
75a37e16e3 Remove elements of order cycle form that coordinators cannot edit 2015-03-27 15:56:07 +11:00
Rob Harrington
f8a9652333 Moving SASS comments to thier own lines 2015-03-27 15:56:07 +11:00
Rob Harrington
75ed259554 Conditionally show input for coordinator
Conflicts:
	app/views/admin/order_cycles/_form.html.haml
2015-03-27 15:56:07 +11:00
Rob Harrington
a9c7e4b716 Order cycles index shows all OrderCycles I am involved in 2015-03-27 15:56:06 +11:00
Rob Harrington
0b082c964b Restricting which enterprises can coordinate an order cycle 2015-03-27 15:51:27 +11:00
Rohan Mitchell
8037811735 Only make new enterprises as hubs when current user *owns*, not just manages a hub. 2015-03-27 14:38:21 +11:00
Rohan Mitchell
0ed1eeffd6 When registering a new enterprise, if user is signed in, owns a hub and is not making a producer, the new enterprise becomes a hub 2015-03-27 14:05:58 +11:00
Rohan Mitchell
d471368412 Spacing 2015-03-27 13:09:25 +11:00
Rohan Mitchell
09a102bd8b When an enterprise user with a hub creates a new producer, it does not default to sells any #453 2015-03-27 12:02:20 +11:00
Rohan Mitchell
d8656a36c6 Consistency in tax calculations, remove some unneeded local vars 2015-03-25 16:31:15 +11:00
Rohan Mitchell
89d4a59e9d Extract order total tax calculations to model 2015-03-25 16:27:29 +11:00
Rohan Mitchell
84f3097217 Calculate total tax from the tax included in all the adjustments on the order 2015-03-25 16:27:29 +11:00
Rohan Mitchell
333a4ecf2f Include enterprise fee tax on sales tax report 2015-03-25 16:27:29 +11:00
Rohan Mitchell
40b4edeca1 Replace zoned_order factory with zone_with_member. In practice, former had issues with circular dependencies. 2015-03-25 16:27:29 +11:00
Rohan Mitchell
9650692699 Calculate total tax on enterprise fees for an order 2015-03-25 16:27:29 +11:00
Rohan Mitchell
69dc92dec1 Create factories zoned_order and taxed_product 2015-03-25 16:27:29 +11:00
Rohan Mitchell
d489e06009 Retrieve line item sales tax from included_tax rather than tax amount 2015-03-25 16:27:29 +11:00
Rohan Mitchell
daa30ed518 Retrieve the shipping tax on the order instead of calculating it from scratch 2015-03-25 16:27:29 +11:00
Rohan Mitchell
7fb8370c36 Look up shipping tax on an order 2015-03-25 16:27:29 +11:00
Rohan Mitchell
e2a4b9a898 Fix specs that relied on the old login page which we now redirect to the new page 2015-03-25 12:11:06 +11:00
Rohan Mitchell
2a7a106ad8 Merge branch 'folklabs-currency-config' 2015-03-25 11:54:06 +11:00
Rohan Mitchell
1005a06583 Merge branch 'currency-config' of https://github.com/folklabs/openfoodnetwork into folklabs-currency-config 2015-03-25 11:39:43 +11:00
Rohan Mitchell
c36272ead6 Switch to update_column, which will not run geocoding callback of Enterprise 2015-03-25 11:37:10 +11:00
Rohan Mitchell
c6ddf36856 Make migration reversible 2015-03-25 11:35:59 +11:00
Rohan Mitchell
ebb3688add Merge branch 'migrations' of https://github.com/folklabs/openfoodnetwork into folklabs-migrations 2015-03-25 11:30:00 +11:00
Rohan Mitchell
5da9bdc614 Merge branch 'victornava-legacy-login-fix' 2015-03-25 10:37:14 +11:00
Paul Mackay
af9a7a2ed4 #443: Support currency configuration. Fix LOCALE variable name. 2015-03-24 15:34:45 +00:00
Paul Mackay
fcfb1aeb87 #440: Try removing validation from update (to prevent geocoding). 2015-03-23 14:24:16 +00:00
Paul Mackay
e39d2eb113 #440: Reset Enterprise columns before querying them. 2015-03-23 13:47:44 +00:00
summerscope
7090bb518b Tweaking logic for alert bar to make messages more human readable for all use cases. 2015-03-20 14:24:59 +11:00
summerscope
0b1857771e Finally got this slide animation working. stupid angular documentation!
ref: http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html
2015-03-20 13:09:45 +11:00
summerscope
938eff8482 More layout tweaks to enterprise modal template 2015-03-19 16:13:47 +11:00
summerscope
b99e94cecf WIP on producer and product modals 2015-03-19 16:02:52 +11:00
summerscope
1f97052954 Add a min height to modals so they are not quite so stupidly small when not enough content suppied by users 2015-03-19 15:05:14 +11:00
summerscope
c76aa1d1c2 WIP on product modal 2015-03-19 14:52:09 +11:00
summerscope
cdd41ad651 change animation class 2015-03-19 14:52:00 +11:00
summerscope
3c61bf9cc4 Styling for no image available on product modal overlay 2015-03-19 14:51:41 +11:00
summerscope
8a0bbb374c Animation WIP 2015-03-19 14:51:23 +11:00
summerscope
4e54a3c48e Updating no image all grey, large version larger 2015-03-19 14:50:50 +11:00
Rob Harrington
bfe7f49033 Show and hide search box 2015-03-18 12:01:53 +11:00
Rohan Mitchell
a6f0d8f69a Show a nice error message instead of 500 error when deleting a referenced order cycle 2015-03-16 12:42:35 +11:00
Rohan Mitchell
95c09315f5 Change class delete-product -> delete-order-cycle 2015-03-16 12:42:05 +11:00
Rohan Mitchell
e38772ada0 Enterprise user can delete unreferenced order cycles 2015-03-16 12:41:06 +11:00
Rohan Mitchell
e125bcf451 Add column header for extra action column 2015-03-16 12:15:43 +11:00
Rohan Mitchell
4491d3cc73 Merge branch 'legacy-login-fix' of https://github.com/victornava/openfoodnetwork into victornava-legacy-login-fix
Conflicts:
	app/views/admin/order_cycles/_row.html.haml
	spec/features/admin/order_cycles_spec.rb
2015-03-16 12:14:54 +11:00
Rob Harrington
2b32252aff Filtering between selector lists 2015-03-15 13:25:04 +11:00
Rob Harrington
29c9f70a1c Rename single line selectors 2015-03-15 12:29:05 +11:00
Rob Harrington
2c1ef4c8c1 Refactoring single line selectors to remove flicker 2015-03-15 12:27:40 +11:00
summerscope
7b1901253c More work on filters for shopfront rewriting as compared to the rest of filter button styles 2015-03-13 17:32:33 +11:00
summerscope
dc1dd2e243 Changing the class .filter-box for shopfront to .filter-shopfront
This prevents the issue with inheritance / styling crossover
2015-03-13 16:06:46 +11:00
summerscope
e3bc7cf894 Styling for search alert on shopfront page 2015-03-13 15:36:06 +11:00
summerscope
e5cc9063e8 Changing the medium input styling to make it same height as taxon filters, and no animation to get big as we want the next row space for tags eventually 2015-03-13 15:35:45 +11:00
summerscope
88edaceee0 Adding a new color to brand colors - yellow light 2015-03-13 15:34:38 +11:00
summerscope
bce64a1ead WIP product modals for shopfront 2015-03-13 15:34:11 +11:00
summerscope
c8c07ed700 Adding position fixed to modals - got lost somehow with upgrading foundation zurb 2015-03-13 12:59:26 +11:00
summerscope
0258fc24f3 Moving comments to own line. New version of SASS does not like comments on same line as declarations. 2015-03-13 12:58:45 +11:00
Rob Harrington
274a7a3c73 Fixing up the one liner filter styling a bit 2015-03-12 09:56:06 +11:00
Victor Nava
f90f7565fb Allow admins to delete Order Cycles 2015-03-11 18:08:09 +11:00
Victor Nava
208fa02ec0 Create a 'Show More' button at the top of the page, next to New Order on on admin order cycles index page 2015-03-11 13:14:45 +11:00
Victor Nava
2c89573441 Shave off a few seconds when showing order_cycles#index by loading order_cycle_enterprises only once. 2015-03-11 11:59:25 +11:00
Rob Harrington
0a300d1802 Rewriting small cart, so that it doesn't break all of the dropdowns on the page (can't use .row within li elements it seems...) 2015-03-06 19:03:46 +11:00
Rob Harrington
12c6878cbe Using vanilla foundation 2015-03-06 19:02:15 +11:00
Rob Harrington
4c4490a9b7 Upgrading foundation-rails and sass 2015-03-06 19:01:39 +11:00
Rob Harrington
578475a403 Filter products list on shop by active properties 2015-03-06 16:14:11 +11:00
Victor Nava
3e2142c3cf Remove the hover / pop-up over the # variants on admin order cycles index page 2015-03-06 11:33:03 +11:00
Rob Harrington
e948bf1591 Only render selector icons if the icon exists 2015-03-06 11:32:01 +11:00
Rob Harrington
06f10398da Adding product property filter to shop page 2015-03-06 11:22:52 +11:00
Rob Harrington
55b8918ea1 Updating comment 2015-03-05 18:38:01 +11:00
Rob Harrington
067b814daa Making legacy filters work properly with filter-selector directive 2015-03-05 18:29:12 +11:00
Rob Harrington
c992937608 Moving taxon-selector directive to correct location 2015-03-05 18:28:49 +11:00
Rob Harrington
cb623b75c1 Generalising taxons-selector -> filter-selector 2015-03-05 18:15:14 +11:00
Victor Nava
3fe1fc3f67 Use dates way into the future so that test that depend on OrderSycles#recently_closed don't break. 2015-03-05 17:32:55 +11:00
Victor Nava
d6c30ae1ef OrderCycle#recently_closed doesn't return orders that are open 2015-03-05 17:28:24 +11:00
Rob Harrington
e7854bcd8e Moving single line selectors to template, making sure other users of taxons-selector still work 2015-03-05 16:38:21 +11:00
Victor Nava
a21bfc909a Remove the suppliers column on admin order cycles index page 2015-03-05 16:12:31 +11:00
Victor Nava
1b709a3e03 Do not load Order Cycles that closed more than a month a go 2015-03-05 16:04:36 +11:00
Rob Harrington
0142f9467a Improve display of overflow selectors 2015-03-05 16:00:53 +11:00
Rob Harrington
24b40182b5 clearAll for product page also clears any text search filter 2015-03-05 15:34:27 +11:00
Rob Harrington
ed94cf57d3 Adding the 'more' box for single-line-selectors 2015-03-05 15:10:42 +11:00
Rob Harrington
5bddada013 Removing unnecessary setter 2015-03-05 12:18:34 +11:00
Rob Harrington
4afef8215a Basic implementation of single line selectors 2015-03-05 12:12:36 +11:00
Victor Nava
4e1eb33ff5 Redirect users to proper login page when they type /login 2015-03-05 11:25:35 +11:00
summerscope
fc7abd5d02 Changing order of tabs at top of shopfront, leaving more room for long shopfront names in about tab 2015-02-25 16:20:10 +11:00
summerscope
469b383781 Properties and shopfront filters with taxons WIP. 2015-02-25 16:04:32 +11:00
summerscope
15144bdddd WIP search input on shopfront page. 2015-02-25 13:18:45 +11:00
summerscope
d43f367f30 Shopfront Properties - WIP layout work 2015-02-25 11:11:09 +11:00
summerscope
304bde3b9e Working on the filters for shopfront properties and updates. 2015-02-25 10:46:51 +11:00
summerscope
e9fca885db WIP layout changes for shopfront top 2015-02-25 10:46:43 +11:00
273 changed files with 6141 additions and 1779 deletions

View File

@@ -15,6 +15,8 @@ gem 'spree_auth_devise', :github => 'spree/spree_auth_devise', :branch => '1-3-s
gem 'spree_paypal_express', :github => "openfoodfoundation/better_spree_paypal_express", :branch => "1-3-stable"
#gem 'spree_paypal_express', :github => "spree-contrib/better_spree_paypal_express", :branch => "1-3-stable"
gem 'delayed_job_active_record'
gem 'daemons'
gem 'comfortable_mexican_sofa'
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
@@ -26,7 +28,7 @@ gem 'angularjs-rails', '1.2.13'
gem 'bugsnag'
gem 'newrelic_rpm'
gem 'haml'
gem 'sass', "~> 3.2"
gem 'sass', "~> 3.3"
gem 'sass-rails', '~> 3.2.3', groups: [:default, :assets]
gem 'aws-sdk'
gem 'db2fog'

View File

@@ -23,7 +23,7 @@ GIT
GIT
remote: git://github.com/openfoodfoundation/spree.git
revision: 4e0075b07acb56864aca89eee3d9670136176c23
revision: afcc23e489eb604a3e2651598a7c8364e2acc7b3
branch: 1-3-stable
specs:
spree (1.3.6.beta)
@@ -123,7 +123,7 @@ GEM
active_link_to (1.0.0)
active_model_serializers (0.8.1)
activemodel (>= 3.0)
activemerchant (1.46.0)
activemerchant (1.48.0)
activesupport (>= 3.2.14, < 5.0.0)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
@@ -177,11 +177,11 @@ GEM
celluloid (0.15.2)
timers (~> 1.1.0)
chronic (0.10.2)
chunky_png (1.3.0)
chunky_png (1.3.4)
climate_control (0.0.3)
activesupport (>= 3.0)
cliver (0.3.2)
cocaine (0.5.5)
cocaine (0.5.7)
climate_control (>= 0.0.3, < 1.0)
coderay (1.0.9)
coffee-rails (3.2.2)
@@ -191,22 +191,33 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.3.3)
colorize (0.7.5)
colorize (0.7.7)
columnize (0.3.6)
comfortable_mexican_sofa (1.6.24)
active_link_to (~> 1.0.0)
paperclip (>= 2.3.0)
rails (>= 3.0.0)
compass (0.12.4)
compass (1.0.3)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.2.17)
compass-rails (1.0.3)
compass (>= 0.12.2, < 0.14)
compass-core (~> 1.0.2)
compass-import-once (~> 1.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
sass (>= 3.3.13, < 3.5)
compass-core (1.0.3)
multi_json (~> 1.0)
sass (>= 3.3.0, < 3.5)
compass-import-once (1.0.5)
sass (>= 3.2, < 3.5)
compass-rails (2.0.4)
compass (~> 1.0.0)
sass-rails (<= 5.0.1)
sprockets (< 2.13)
crack (0.4.1)
safe_yaml (~> 0.9.0)
css_parser (1.3.5)
addressable
daemons (1.2.2)
dalli (2.7.2)
database_cleaner (0.7.1)
db2fog (0.8.0)
@@ -219,6 +230,11 @@ GEM
debugger-ruby_core_source (~> 1.2.3)
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.2.3)
delayed_job (4.0.4)
activesupport (>= 3.0, < 4.2)
delayed_job_active_record (4.0.2)
activerecord (>= 3.0, < 4.2)
delayed_job (>= 3.0, < 4.1)
devise (2.2.8)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
@@ -261,10 +277,9 @@ GEM
foundation-icons-sass-rails (3.0.0)
railties (>= 3.1.1)
sass-rails (>= 3.1.1)
foundation-rails (5.2.2.0)
foundation-rails (5.5.0.0)
railties (>= 3.1.0)
sass (>= 3.2.0)
fssm (0.2.10)
sass (>= 3.2.0, < 3.4)
fuubar (1.3.3)
rspec (>= 2.14.0, < 3.1.0)
ruby-progressbar (~> 1.4)
@@ -332,7 +347,7 @@ GEM
railties (>= 3.1)
money (5.1.1)
i18n (~> 0.6.0)
multi_json (1.10.1)
multi_json (1.11.0)
multi_xml (0.5.5)
net-scp (1.1.2)
net-ssh (>= 2.6.5)
@@ -442,7 +457,7 @@ GEM
ruby-hmac (0.4.0)
ruby-progressbar (1.7.1)
safe_yaml (0.9.5)
sass (3.2.19)
sass (3.3.14)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
@@ -481,7 +496,7 @@ GEM
sprockets (>= 2.0.0)
turn (0.8.3)
ansi
tzinfo (0.3.43)
tzinfo (0.3.44)
uglifier (1.2.4)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
@@ -529,11 +544,13 @@ DEPENDENCIES
comfortable_mexican_sofa
compass-rails
custom_error_message!
daemons
dalli
database_cleaner (= 0.7.1)
db2fog
debugger-linecache
deface!
delayed_job_active_record
factory_girl_rails
figaro
foreigner
@@ -569,7 +586,7 @@ DEPENDENCIES
representative_view
roadie-rails (~> 1.0.3)
rspec-rails
sass (~> 3.2)
sass (~> 3.3)
sass-rails (~> 3.2.3)
shoulda-matchers
simple_form!

View File

@@ -1,4 +1,3 @@
[![Build Status](http://ci.openfood.com.au:8080/buildStatus/icon?job=openfoodweb - tests)](http://ci.openfood.com.au:8080/job/openfoodweb%20-%20tests/)
[![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
# Open Food Network

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,6 +1,6 @@
angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
"$scope", "$http", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey"
($scope, $http, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey) ->
"$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey"
($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey) ->
$scope.loading = true
$scope.initialiseVariables = ->
@@ -42,13 +42,15 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
if $scope.spree_api_key_ok
$http.defaults.headers.common["X-Spree-Token"] = SpreeApiKey
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_primary_producer_eq]=true").then (data) ->
$scope.suppliers = data
$scope.suppliers = $filter('orderBy')(data, 'name')
$scope.suppliers.unshift blankOption()
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_distributor_eq]=true").then (data) ->
$scope.distributors = data
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[sells_in][]=own&q[sells_in][]=any").then (data) ->
$scope.distributors = $filter('orderBy')(data, 'name')
$scope.distributors.unshift blankOption()
ocFetcher = dataFetcher("/api/order_cycles/accessible").then (data) ->
ocFetcher = dataFetcher("/api/order_cycles/accessible?as=distributor&q[orders_close_at_gt]=#{formatDate(daysFromToday(-90))}").then (data) ->
$scope.orderCycles = data
$scope.orderCyclesByID = []
$scope.orderCyclesByID[oc.id] = oc for oc in $scope.orderCycles
$scope.orderCycles.unshift blankOption()
$scope.fetchOrders()
ocFetcher.then ->
@@ -60,7 +62,7 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
$scope.fetchOrders = ->
$scope.loading = true
dataFetcher("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
dataFetcher("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
$scope.resetOrders data
$scope.loading = false
@@ -162,6 +164,11 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
$scope.supplierFilter = $scope.suppliers[0].id
$scope.orderCycleFilter = $scope.orderCycles[0].id
$scope.quickSearch = ""
$scope.$watch "orderCycleFilter", (newVal, oldVal) ->
unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal)
$scope.startDate = $scope.orderCyclesByID[$scope.orderCycleFilter].first_order
$scope.endDate = $scope.orderCyclesByID[$scope.orderCycleFilter].last_order
]
daysFromToday = (days) ->

View File

@@ -4,13 +4,15 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.StatusMessage = StatusMessage
$scope.columns =
producer: {name: "Producer", visible: true}
name: {name: "Name", visible: true}
unit: {name: "Unit", visible: true}
price: {name: "Price", visible: true}
on_hand: {name: "On Hand", visible: true}
category: {name: "Category", visible: false}
available_on: {name: "Available On", visible: false}
producer: {name: "Producer", visible: true}
sku: {name: "SKU", visible: false}
name: {name: "Name", visible: true}
unit: {name: "Unit", visible: true}
price: {name: "Price", visible: true}
on_hand: {name: "On Hand", visible: true}
category: {name: "Category", visible: false}
inherits_properties: {name: "Inherits Properties?", visible: false}
available_on: {name: "Available On", visible: false}
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
@@ -285,6 +287,9 @@ filterSubmitProducts = (productsToFilter) ->
filteredMaster ?= { id: product.master.id }
filteredMaster.display_as = product.master.display_as
if product.hasOwnProperty("sku")
filteredProduct.sku = product.sku
hasUpdatableProperty = true
if product.hasOwnProperty("name")
filteredProduct.name = product.name
hasUpdatableProperty = true
@@ -307,6 +312,9 @@ filterSubmitProducts = (productsToFilter) ->
if product.hasOwnProperty("category_id")
filteredProduct.primary_taxon_id = product.category_id
hasUpdatableProperty = true
if product.hasOwnProperty("inherits_properties")
filteredProduct.inherits_properties = product.inherits_properties
hasUpdatableProperty = true
if product.hasOwnProperty("available_on")
filteredProduct.available_on = product.available_on
hasUpdatableProperty = true

View File

@@ -1 +1 @@
angular.module("admin.enterprise_groups", ["admin.side_menu", "admin.users"])
angular.module("admin.enterprise_groups", ["admin.side_menu", "admin.users", "textAngular"])

View File

@@ -13,6 +13,7 @@ angular.module("admin.enterprises")
{ name: 'About', icon_class: "icon-pencil" }
{ name: 'Business Details', icon_class: "icon-briefcase" }
{ name: 'Images', icon_class: "icon-picture" }
{ name: "Properties", icon_class: "icon-tags", show: "showProperties()" }
{ name: "Shipping Methods", icon_class: "icon-truck", show: "showShippingMethods()" }
{ name: "Payment Methods", icon_class: "icon-money", show: "showPaymentMethods()" }
{ name: "Enterprise Fees", icon_class: "icon-tasks", show: "showEnterpriseFees()" }
@@ -28,6 +29,9 @@ angular.module("admin.enterprises")
else
true
$scope.showProperties = ->
!!$scope.Enterprise.is_primary_producer
$scope.showShippingMethods = ->
enterprisePermissions.can_manage_shipping_methods && $scope.Enterprise.sells != "none"

View File

@@ -1,11 +1,10 @@
angular.module('admin.order_cycles', ['ngResource'])
.controller('AdminCreateOrderCycleCtrl', ['$scope', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', ($scope, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
$scope.enterprises = Enterprise.index()
.controller('AdminCreateOrderCycleCtrl', ['$scope', '$filter', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', ($scope, $filter, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index()
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.order_cycle = OrderCycle.order_cycle
$scope.order_cycle.coordinator_id = ocInstance.coordinator_id
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded
@@ -28,14 +27,14 @@ angular.module('admin.order_cycles', ['ngResource'])
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangesVariants = ->
OrderCycle.incomingExchangesVariants()
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.participatingEnterprises = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds()
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.toggleProducts = ($event, exchange) ->
$event.preventDefault()
@@ -80,12 +79,12 @@ angular.module('admin.order_cycles', ['ngResource'])
OrderCycle.create()
])
.controller('AdminEditOrderCycleCtrl', ['$scope', '$location', 'OrderCycle', 'Enterprise', 'EnterpriseFee', ($scope, $location, OrderCycle, Enterprise, EnterpriseFee) ->
$scope.enterprises = Enterprise.index()
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index()
.controller('AdminEditOrderCycleCtrl', ['$scope', '$filter', '$location', 'OrderCycle', 'Enterprise', 'EnterpriseFee', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee) ->
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
$scope.order_cycle = OrderCycle.load(order_cycle_id)
$scope.loaded = ->
@@ -109,14 +108,14 @@ angular.module('admin.order_cycles', ['ngResource'])
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangesVariants = ->
OrderCycle.incomingExchangesVariants()
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.participatingEnterprises = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds()
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.toggleProducts = ($event, exchange) ->
$event.preventDefault()

View File

@@ -1,8 +1,9 @@
angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee) ->
$scope.enterprises = Enterprise.index (enterprises) =>
$scope.init(enterprises)
$scope.enterprise_fees = EnterpriseFee.index()
$scope.order_cycle = OrderCycle.order_cycle
angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
# TODO: make this a get method, which only fetches one enterprise
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
$scope.init(enterprises)
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.init = (enterprises) ->
enterprise = enterprises[Object.keys(enterprises)[0]]

View File

@@ -2,8 +2,8 @@ angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl",
$scope.orderCycleId = ->
$location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.enterprises = Enterprise.index()
$scope.enterprise_fees = EnterpriseFee.index()
$scope.enterprises = Enterprise.index(order_cycle_id: $scope.orderCycleId())
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.orderCycleId())
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
$scope.init()

View File

@@ -0,0 +1,6 @@
angular.module("admin.order_cycles").filter "filterExchangeVariants", ->
return (variants, rules) ->
if variants? && rules?
return (variant for variant in variants when variant in rules)
else
return []

View File

@@ -0,0 +1,4 @@
angular.module("admin.order_cycles").filter "visibleProductVariants", ->
return (product, exchange, rules) ->
variants = product.variants.concat( [{ "id": product.master_id}] )
return (variant for variant in variants when variant.id in rules[exchange.enterprise_id])

View File

@@ -0,0 +1,3 @@
angular.module("admin.order_cycles").filter "visibleProducts", ($filter) ->
return (products, exchange, rules) ->
return (product for product in products when $filter('visibleProductVariants')(product, exchange, rules).length > 0)

View File

@@ -1,24 +1,28 @@
angular.module('admin.order_cycles').factory('Enterprise', ($resource) ->
Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {'index': {method: 'GET', isArray: true}})
Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {
'index':
method: 'GET'
isArray: true
params:
order_cycle_id: '@order_cycle_id'
coordinator_id: '@coordinator_id'
})
{
Enterprise: Enterprise
enterprises: {}
supplied_products: []
loaded: false
index: (callback=null) ->
service = this
Enterprise.index (data) ->
index: (params={}, callback=null) ->
Enterprise.index params, (data) =>
for enterprise in data
service.enterprises[enterprise.id] = enterprise
@enterprises[enterprise.id] = enterprise
for product in enterprise.supplied_products
service.supplied_products.push(product)
@supplied_products.push(product)
service.loaded = true
(callback || angular.noop)(service.enterprises)
@loaded = true
(callback || angular.noop)(@enterprises)
this.enterprises
@@ -40,4 +44,4 @@ angular.module('admin.order_cycles').factory('Enterprise', ($resource) ->
numVariants += if product.variants.length == 0 then 1 else product.variants.length
numVariants
})
})

View File

@@ -1,18 +1,23 @@
angular.module('admin.order_cycles').factory('EnterpriseFee', ($resource) ->
EnterpriseFee = $resource('/admin/enterprise_fees/:enterprise_fee_id.json', {}, {'index': {method: 'GET', isArray: true}})
EnterpriseFee = $resource('/admin/enterprise_fees/for_order_cycle/:enterprise_fee_id.json', {}, {
'index':
method: 'GET'
isArray: true
params:
order_cycle_id: '@order_cycle_id'
coordinator_id: '@coordinator_id'
})
{
EnterpriseFee: EnterpriseFee
enterprise_fees: {}
loaded: false
index: ->
service = this
EnterpriseFee.index (data) ->
service.enterprise_fees = data
service.loaded = true
index: (params={}) ->
EnterpriseFee.index params, (data) =>
@enterprise_fees = data
@loaded = true
forEnterprise: (enterprise_id) ->
enterprise_fee for enterprise_fee in this.enterprise_fees when enterprise_fee.enterprise_id == enterprise_id
enterprise_fee for enterprise_fee in @enterprise_fees when enterprise_fee.enterprise_id == enterprise_id
})

View File

@@ -1,14 +1,12 @@
angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) ->
OrderCycle = $resource '/admin/order_cycles/:order_cycle_id.json', {}, {
OrderCycle = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
'index': { method: 'GET', isArray: true}
'new' : { method: 'GET', params: { action_name: "new" } }
'create': { method: 'POST'}
'update': { method: 'PUT'}}
{
order_cycle:
incoming_exchanges: []
outgoing_exchanges: []
coordinator_fees: []
order_cycle: {}
loaded: false
@@ -24,7 +22,9 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
exchange.showProducts = !exchange.showProducts
setExchangeVariants: (exchange, variants, selected) ->
exchange.variants[variant] = selected for variant in variants
direction = if exchange.incoming then "incoming" else "outgoing"
editable = @order_cycle["editable_variants_for_#{direction}_exchanges"][exchange.enterprise_id] || []
exchange.variants[variant] = selected for variant in variants when variant in editable
addSupplier: (new_supplier_id) ->
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
@@ -84,6 +84,20 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
for exchange in this.order_cycle.outgoing_exchanges
exchange.variants[variant_id] = false
new: (params, callback=null) ->
OrderCycle.new params, (oc) =>
delete oc.$promise
delete oc.$resolved
angular.extend(@order_cycle, oc)
@order_cycle.incoming_exchanges = []
@order_cycle.outgoing_exchanges = []
delete(@order_cycle.exchanges)
@loaded = true
(callback || angular.noop)(@order_cycle)
@order_cycle
load: (order_cycle_id, callback=null) ->
service = this
OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) ->
@@ -127,6 +141,7 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
dataForSubmit: ->
data = this.deepCopy()
data = this.stripNonSubmittableAttributes(data)
data = this.removeInactiveExchanges(data)
data = this.translateCoordinatorFees(data)
data = this.translateExchangeFees(data)
@@ -147,6 +162,14 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
data
stripNonSubmittableAttributes: (order_cycle) ->
delete order_cycle.id
delete order_cycle.viewing_as_coordinator
delete order_cycle.editable_variants_for_incoming_exchanges
delete order_cycle.editable_variants_for_outgoing_exchanges
delete order_cycle.visible_variants_for_outgoing_exchanges
order_cycle
removeInactiveExchanges: (order_cycle) ->
order_cycle.incoming_exchanges =
(exchange for exchange in order_cycle.incoming_exchanges when exchange.active)

View File

@@ -36,4 +36,4 @@
$ ->
# Hacky fix for issue - http://foundation.zurb.com/forum/posts/2112-foundation-5100-syntax-error-in-js
Foundation.set_namespace ""
#$(document).foundation()
$(document).foundation()

View File

@@ -1,5 +1,4 @@
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Enterprises, Search, FilterSelectorsService) ->
$scope.Enterprises = Enterprises
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService) ->
$scope.totalActive = FilterSelectorsService.totalActive
$scope.clearAll = FilterSelectorsService.clearAll
$scope.filterText = FilterSelectorsService.filterText

View File

@@ -0,0 +1,14 @@
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap) ->
$scope.Enterprises = Enterprises
group_enterprises_ids = group_enterprises.map (enterprise) =>
enterprise.id
is_in_group = (enterprise) ->
group_enterprises_ids.indexOf(enterprise.id) != -1
$scope.group_producers = Enterprises.producers.filter is_in_group
$scope.group_hubs = Enterprises.hubs.filter is_in_group
$scope.map = angular.copy MapConfiguration.options
$scope.mapMarkers = OfnMap.enterprise_markers group_enterprises

View File

@@ -1,4 +1,4 @@
Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart) ->
Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart, Taxons, Properties) ->
$scope.Products = Products
$scope.Cart = Cart
$scope.totalActive = FilterSelectorsService.totalActive
@@ -9,6 +9,9 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle,
$scope.limit = 3
$scope.order_cycle = OrderCycle.order_cycle
$scope.$watch "Products.loading", (newValue, oldValue) ->
$scope.$broadcast("loadFilterSelectors") if !newValue
$scope.incrementLimit = ->
if $scope.limit < Products.products.length
$scope.limit = $scope.limit + 1
@@ -17,3 +20,17 @@ Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle,
code = e.keyCode || e.which
if code == 13
e.preventDefault()
$scope.appliedTaxonsList = ->
$scope.activeTaxons.map( (taxon_id) ->
Taxons.taxons_by_id[taxon_id].name
).join(" & ") if $scope.activeTaxons?
$scope.appliedPropertiesList = ->
$scope.activeProperties.map( (property_id) ->
Properties.properties_by_id[property_id].name
).join(" & ") if $scope.activeProperties?
$scope.clearAll = ->
$scope.query = ""
FilterSelectorsService.clearAll()

View File

@@ -3,7 +3,7 @@ Darkswarm.controller "RegistrationCtrl", ($scope, RegistrationService, Enterpris
$scope.enterprise = EnterpriseRegistrationService.enterprise
$scope.select = RegistrationService.select
$scope.steps = ['details','contact','type','about','images','social']
$scope.steps = ['details', 'contact', 'type', 'about', 'images', 'social']
$scope.countries = availableCountries

View File

@@ -6,10 +6,10 @@ Darkswarm.directive "activeSelector", ->
replace: true
templateUrl: 'active_selector.html'
link: (scope, elem, attr)->
scope.selector.emit = scope.emit
elem.bind "click", ->
scope.$apply ->
scope.selector.active = !scope.selector.active
# This function is a convention, e.g. a callback on the scope applied when active changes
scope.emit() if scope.emit
unless scope.readOnly && scope.readOnly()
scope.selector.emit = scope.emit
elem.bind "click", ->
scope.$apply ->
scope.selector.active = !scope.selector.active
# This function is a convention, e.g. a callback on the scope applied when active changes
scope.emit() if scope.emit

View File

@@ -0,0 +1,54 @@
Darkswarm.directive "filterSelector", (FilterSelectorsService)->
# Automatically builds activeSelectors for taxons
# Lots of magic here
restrict: 'E'
replace: true
scope:
objects: "&"
activeSelectors: "=?"
allSelectors: "=?" # Optional
templateUrl: "filter_selector.html"
link: (scope, elem, attr)->
selectors_by_id = {}
selectors = null # To get scoping/closure right
scope.readOnly = ->
!attr.activeSelectors?
scope.emit = ->
scope.activeSelectors = selectors.filter (selector)->
selector.active
.map (selector)->
selector.object.id
# This can be called from a parent scope
# when data has been loaded, in order to pass
# selectors up
scope.$on 'loadFilterSelectors', ->
scope.allSelectors = scope.selectors() if attr.allSelectors?
scope.$watchCollection "selectors()", (newValue, oldValue) ->
scope.allSelectors = scope.selectors() if attr.allSelectors?
# Build a list of selectors
scope.selectors = ->
# Generate a selector for each object.
# NOTE: THESE ARE MEMOIZED to stop new selectors from being created constantly, otherwise function always returns non-identical results
# This means the $digest cycle can never close and times out
# See http://stackoverflow.com/questions/19306452/how-to-fix-10-digest-iterations-reached-aborting-error-in-angular-1-2-fil
selectors = []
for id, object of scope.objects()
if selector = selectors_by_id[id]
selectors.push selector
else
selector = selectors_by_id[id] = FilterSelectorsService.new
object: object
selectors.push selector
selectors
scope.ifDefined = (value, if_undefined) ->
if angular.isDefined(value)
value
else
if_undefined

View File

@@ -0,0 +1,73 @@
Darkswarm.directive 'singleLineSelectors', ($timeout, $filter) ->
restrict: 'E'
templateUrl: "single_line_selectors.html"
scope:
objects: "&"
activeSelectors: "="
selectorName: "@activeSelectors"
link: (scope,element,attrs) ->
scope.fitting = false
scope.overFlowSelectors = ->
return [] unless scope.allSelectors?
$filter('filter')(scope.allSelectors, { fits: false })
scope.selectedOverFlowSelectors = ->
$filter('filter')(scope.overFlowSelectors(), { active: true })
# had to duplicate this to make overflow selectors work
scope.emit = ->
scope.activeSelectors = scope.allSelectors.filter (selector)->
selector.active
.map (selector)->
selector.object.id
# From: http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
debouncer = (func, timeout) ->
timeoutID = undefined
timeout = timeout or 50
->
subject = this
args = arguments
clearTimeout timeoutID
timeoutID = setTimeout(->
func.apply subject, Array::slice.call(args)
, timeout)
loadWidths = ->
$(element).find("li").not(".more").each (i) ->
scope.allSelectors[i].width = $(this).outerWidth(true)
return null # So we don't exit the loop weirdly
fit = ->
used = $(element).find("li.more").outerWidth(true)
used += selector.width for selector in scope.allSelectors when selector.fits
available = $(element).parent(".filter-shopfront").innerWidth() - used
if available > 0
for selector in scope.allSelectors when !selector.fits
available -= selector.width
selector.fits = true if available > 0
else
if scope.allSelectors.length > 0
for i in [scope.allSelectors.length-1..0]
selector = scope.allSelectors[i]
if !selector.fits
continue
else
if available < 0
selector.fits = false
available += selector.width
scope.fitting = false
scope.$watchCollection "allSelectors", ->
if scope.allSelectors?
scope.fitting = true
selector.fits = true for selector in scope.allSelectors
$timeout(loadWidths, 0, true).then ->
$timeout fit, 0, true
$(window).resize debouncer (e) ->
scope.fitting = true
if scope.allSelectors?
$timeout fit, 0, true

View File

@@ -1,43 +0,0 @@
Darkswarm.directive "taxonSelector", (FilterSelectorsService)->
# Automatically builds activeSelectors for taxons
# Lots of magic here
restrict: 'E'
replace: true
scope:
objects: "&"
results: "="
templateUrl: "taxon_selector.html"
link: (scope, elem, attr)->
selectors_by_id = {}
selectors = null # To get scoping/closure right
scope.emit = ->
scope.results = selectors.filter (selector)->
selector.active
.map (selector)->
selector.taxon.id
# Build hash of unique taxons, each of which gets an ActiveSelector
scope.selectors = ->
taxons = {}
selectors = []
for object in scope.objects()
for taxon in object.taxons
taxons[taxon.id] = taxon
if object.supplied_taxons
for taxon in object.supplied_taxons
taxons[taxon.id] = taxon
# Generate a selector for each taxon.
# NOTE: THESE ARE MEMOIZED to stop new selectors from being created constantly, otherwise function always returns non-identical results
# This means the $digest cycle can never close and times out
# See http://stackoverflow.com/questions/19306452/how-to-fix-10-digest-iterations-reached-aborting-error-in-angular-1-2-fil
for id, taxon of taxons
if selector = selectors_by_id[id]
selectors.push selector
else
selector = selectors_by_id[id] = FilterSelectorsService.new
taxon: taxon
selectors.push selector
selectors

View File

@@ -0,0 +1,16 @@
Darkswarm.filter 'properties', ()->
# Filter anything that responds to object.properties
(objects, ids) ->
objects ||= []
ids ?= []
if ids.length == 0
# No properties selected, pass all objects through.
objects
else
objects.filter (obj)->
properties = obj.properties
# Combine object properties with supplied properties, if they exist.
# properties = properties.concat obj.supplied_properties if obj.supplied_properties
# Match property array.
properties.some (property)->
property.id in ids

View File

@@ -0,0 +1,7 @@
Darkswarm.filter 'propertiesOf', ->
(objects)->
properties = {}
for object in objects
for property in object.properties
properties[property.id] = property
properties

View File

@@ -0,0 +1,7 @@
Darkswarm.filter 'propertiesWithValuesOf', ->
(objects)->
propertiesWithValues = {}
for object in objects
for property in object.properties_with_values
propertiesWithValues[property.id] = property
propertiesWithValues

View File

@@ -0,0 +1,10 @@
Darkswarm.filter 'taxonsOf', ->
(objects)->
taxons = {}
for object in objects
for taxon in object.taxons
taxons[taxon.id] = taxon
if object.supplied_taxons
for taxon in object.supplied_taxons
taxons[taxon.id] = taxon
taxons

View File

@@ -25,7 +25,7 @@ Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location, Redir
active: Navigation.active
close: ->
if location.pathname == "/"
if location.pathname in ["/", "/checkout"]
Navigation.navigate "/"
else
Loading.message = "Taking you back to the home page"

View File

@@ -1,11 +1,13 @@
Darkswarm.factory "OfnMap", (Enterprises, EnterpriseModal, visibleFilter)->
Darkswarm.factory "OfnMap", (Enterprises, EnterpriseModal, visibleFilter) ->
new class OfnMap
constructor: ->
@enterprises = (@extend(enterprise) for enterprise in visibleFilter(Enterprises.enterprises))
@enterprises = @enterprise_markers(Enterprises.enterprises)
enterprise_markers: (enterprises) ->
@extend(enterprise) for enterprise in visibleFilter(enterprises)
# Adding methods to each enterprise
extend: (enterprise)->
extend: (enterprise) ->
new class MapMarker
# We're whitelisting attributes because GMaps tries to crawl
# our data, and our data is recursive, so it breaks

View File

@@ -1,27 +1,30 @@
Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Cart, Variants) ->
Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Properties, Cart, Variants) ->
new class Products
constructor: ->
@update()
# TODO: don't need to scope this into object
# Already on object as far as controller scope is concerned
products: null
loading: true
update: =>
@loading = true
@loading = true
@products = $resource("/shop/products").query (products)=>
@extend() && @dereference()
@registerVariants()
@registerVariants()
@registerVariantsWithCart()
@loading = false
@
dereference: ->
for product in @products
product.supplier = Enterprises.enterprises_by_id[product.supplier.id]
Dereferencer.dereference product.taxons, Taxons.taxons_by_id
product.properties = angular.copy(product.properties_with_values)
Dereferencer.dereference product.properties, Properties.properties_by_id
# May return different objects! If the variant has already been registered
# by another service, we fetch those
registerVariants: ->
@@ -45,7 +48,7 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Car
prices = (v.price for v in product.variants)
product.price = Math.min.apply(null, prices)
product.hasVariants = product.variants?.length > 0
product.primaryImage = product.images[0]?.small_url if product.images
product.primaryImageOrMissing = product.primaryImage || "/assets/noimage/small.png"
product.largeImage = product.images[0]?.large_url if product.images

View File

@@ -0,0 +1,9 @@
Darkswarm.factory "Properties", (properties)->
new class Properties
# Populate ProductProperties.properties from json in page.
properties: properties
properties_by_id: {}
constructor: ->
# Map properties to id/object pairs for lookup.
for property in @properties
@properties_by_id[property.id] = property

View File

@@ -1,2 +1,3 @@
%li{"ng-class" => "{active: selector.active}"}
%a{"ng-transclude" => true}
%li{ ng: { class: "{active: selector.active}" } }
%a{ "tooltip" => "{{selector.object.value}}", "tooltip-placement" => "bottom",
ng: { transclude: true, class: "{active: selector.active, 'has-tip': selector.object.value}" } }

View File

@@ -0,0 +1,4 @@
%div{bindonce:true, style: "display: inline-block" }
%active-selector{ ng: { repeat: "selector in allSelectors", show: "ifDefined(selector.fits, true)" } }
%render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"} }
%span{"bo-text" => "selector.object.name"}

View File

@@ -1,14 +1,11 @@
%div.contact-container{bindonce: true}
%div.modal-centered{"bo-if" => "enterprise.email || enterprise.website || enterprise.phone"}
%p.modal-header Contact
%p{"ng-if" => "enterprise.phone"}
{{ enterprise.phone }}
%p{"bo-if" => "enterprise.phone", "bo-text" => "enterprise.phone"}
%p.word-wrap{"ng-if" => "enterprise.email"}
%a{"ng-href" => "{{enterprise.email | stripUrl}}", target: "_blank", mailto: true}
%span.email
{{ enterprise.email | stripUrl }}
%a{"bo-href" => "enterprise.email | stripUrl", target: "_blank", mailto: true}
%span.email{"bo-bind" => "enterprise.email | stripUrl"}
%p.word-wrap{"ng-if" => "enterprise.website"}
%a{"ng-href" => "http://{{enterprise.website | stripUrl}}", target: "_blank" }
{{ enterprise.website | stripUrl }}
%a{"bo-href-i" => "http://{{enterprise.website | stripUrl}}", target: "_blank", "bo-bind" => "enterprise.website | stripUrl"}

View File

@@ -1,9 +1,28 @@
.row{bindonce: true}
.row{bindonce: true}
.small-12.large-8.columns
%div{"ng-if" => "enterprise.long_description.length > 0 || enterprise.logo"}
/ TODO: Rob add logic for taxons and properties too:
/ %div{"ng-if" => "enterprise.long_description.length > 0 || enterprise.logo"}
%div
%p.modal-header About
.about-container
%img.enterprise-logo{"bo-src" => "enterprise.logo", "bo-if" => "enterprise.logo"}
/ TODO: Rob - add in taxons and properties and property pop-overs
-# TODO: Add producer taxons and properties here
-# %div
-# %span.filter-shopfront.taxon-selectors
-# %ul.inline-block
-# %li
-# %a.button.tiny.disabled Grains
-# %li
-# %a.button.tiny.disabled Dairy
-#
-# %span.filter-shopfront.property-selectors.pad-top
-# %ul.inline-block
-# %li
-# %a.button.tiny Organic certified
-# / TODO: Rob - need popover, use will's directive or this? http://pineconellc.github.io/angular-foundation/
-#
.about-container.pad-top
%img.enterprise-logo{"bo-src" => "enterprise.logo", "bo-if" => "enterprise.logo"}
%p.text-small{"ng-bind-html" => "enterprise.long_description"}
.small-12.large-4.columns
%ng-include{src: "'partials/contact.html'"}

View File

@@ -1,13 +1,13 @@
.highlight{"ng-class" => "{'is_distributor' : enterprise.is_distributor}"}
.highlight{bindonce: true, "ng-class" => "{'is_distributor' : enterprise.is_distributor}"}
.highlight-top.row
.small-12.medium-7.large-8.columns
%h3{"ng-if" => "enterprise.is_distributor"}
%a{"bo-href" => "enterprise.path", "ofn-empties-cart" => "enterprise", bindonce: true}
%a{"bo-href" => "enterprise.path", "ofn-empties-cart" => "enterprise"}
%i{"ng-class" => "enterprise.icon_font"}
%span {{ enterprise.name }}
%span{"bo-text" => "enterprise.name"}
%h3{"ng-if" => "!enterprise.is_distributor", "ng-class" => "{'is_producer' : enterprise.is_primary_producer}"}
%i{"ng-class" => "enterprise.icon_font"}
%span {{ enterprise.name }}
%span{"bo-text" => "enterprise.name"}
.small-12.medium-5.large-4.columns.text-right.small-only-text-left
%p {{ [enterprise.address.city, enterprise.address.state_name] | printArray}}
%img.hero-img{"ng-src" => "{{enterprise.promo_image}}"}
%p{"bo-bind" => "[enterprise.address.city, enterprise.address.state_name] | printArray"}
%img.hero-img{"bo-src" => "enterprise.promo_image"}

View File

@@ -1,19 +1,19 @@
%div.modal-centered{"ng-if" => "enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
%div.modal-centered{bindonce: true, "bo-if" => "enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
%p.modal-header Follow
.follow-icons{bindonce: true}
%span{"ng-if" => "enterprise.twitter"}
%a{"ng-href" => "http://twitter.com/{{enterprise.twitter}}", target: "_blank"}
.follow-icons
%span{"bo-if" => "enterprise.twitter"}
%a{"bo-href-i" => "http://twitter.com/{{enterprise.twitter}}", target: "_blank"}
%i.ofn-i_041-twitter
%span{"ng-if" => "enterprise.facebook"}
%a{"ng-href" => "http://{{enterprise.facebook | stripUrl}}", target: "_blank"}
%span{"bo-if" => "enterprise.facebook"}
%a{"bo-href-i" => "http://{{enterprise.facebook | stripUrl}}", target: "_blank"}
%i.ofn-i_044-facebook
%span{"ng-if" => "enterprise.linkedin"}
%a{"ng-href" => "http://{{enterprise.linkedin | stripUrl}}", target: "_blank"}
%span{"bo-if" => "enterprise.linkedin"}
%a{"bo-href-i" => "http://{{enterprise.linkedin | stripUrl}}", target: "_blank"}
%i.ofn-i_042-linkedin
%span{"ng-if" => "enterprise.instagram"}
%a{"ng-href" => "http://instagram.com/{{enterprise.instagram}}", target: "_blank"}
%span{"bo-if" => "enterprise.instagram"}
%a{"bo-href-i" => "http://instagram.com/{{enterprise.instagram}}", target: "_blank"}
%i.ofn-i_043-instagram

View File

@@ -2,7 +2,7 @@
.cta-container.small-12.columns
%label
Shop for
%strong {{enterprise.name}}
%strong{"bo-text" => "enterprise.name"}
products at:
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs",
"bo-href" => "hub.path",
@@ -10,7 +10,7 @@
"ofn-empties-cart" => "hub"}
%i.ofn-i_033-open-sign{"bo-if" => "hub.active"}
%i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"}
.hub-name {{hub.name}}
.button-address {{ hub.address.city }} , {{hub.address.state_name}}
.hub-name{"bo-text" => "hub.name"}
.button-address{"bo-bind" => "[hub.address.city, hub.address.state_name] | printArray"}
/ %i.ofn-i_007-caret-right

View File

@@ -19,6 +19,6 @@
"ofn-empties-cart" => "enterprise"}
%i.ofn-i_033-open-sign{"bo-if" => "enterprise.active"}
%i.ofn-i_032-closed-sign{"bo-if" => "!enterprise.active"}
.hub-name {{enterprise.name}}
.button-address {{ enterprise.address.city }} , {{enterprise.address.state_name}}
.hub-name{"bo-text" => "enterprise.name"}
.button-address{"bo-bind" => "[enterprise.address.city, enterprise.address.state_name] | printArray"}
/ %i.ofn-i_007-caret-right

View File

@@ -1,9 +1,28 @@
.row
.columns.small-12.large-6
%img.product-img{"ng-src" => "{{product.largeImage}}", "ng-if" => "product.largeImage"}
.row{bindonce: true}
.columns.small-12.large-6.product-header
%h2
/ %render-svg{path: "{{product.primary_taxon.icon}}"}
{{product.name}}
%p {{product.description}}
%h3{"bo-text" => "product.name"}
%span
%em from
%span.avenir{"bo-text" => "enterprise.name"}
%br
.filter-shopfront.taxon-selectors.inline-block
%ul
%filter-selector{ objects: "[product] | taxonsOf" }
.filter-shopfront.property-selectors.inline-block
%ul
%filter-selector{ objects: "[product] | propertiesWithValuesOf" }
%div{"ng-if" => "product.description"}
%hr
%p.text-small{"bo-text" => "product.description"}
%hr
.columns.small-12.large-6
%img.product-img{"bo-src" => "product.largeImage", "bo-if" => "product.largeImage"}
%img.product-img.placeholder{"bo-src" => "'/assets/noimage/large.png'", "bo-if" => "!product.largeImage"}
%ng-include{src: "'partials/close.html'"}

View File

@@ -40,6 +40,16 @@
.field
%label{ for: 'enterprise_acn' } ACN:
%input.chunky{ id: 'enterprise_acn', placeholder: "eg. 123 456 789", ng: { model: 'enterprise.acn' } }
.row
.small-12.columns
.field
%label{ for: 'enterprise_charges_sales_tax' }= t(:charges_sales_tax)
%input{ id: 'enterprise_charges_sales_tax_true', type: 'radio', name: 'charges_sales_tax', value: 'true', required: true, ng: { model: 'enterprise.charges_sales_tax' } }
%label{ for: 'enterprise_charges_sales_tax_true' } Yes
%input{ id: 'enterprise_charges_sales_tax_false', type: 'radio', name: 'charges_sales_tax', value: 'false', required: true, ng: { model: 'enterprise.charges_sales_tax' } }
%label{ for: 'enterprise_charges_sales_tax_false' } No
%span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } }
You need to make a selection.
.row.buttons.pad-top
.small-12.columns

View File

@@ -0,0 +1,14 @@
%ul
-# In order for the single-line-selector scope to have access to the available selectors,
%filter-selector{objects: "objects()", "active-selectors" => "activeSelectors", "all-selectors" => "allSelectors" }
%li.more{ ng: { show: "overFlowSelectors().length > 0 || fitting" } }
%a.dropdown{ data: { dropdown: "{{ 'show-more-' + selectorName }}" }, ng: { class: "{active: selectedOverFlowSelectors().length > 0}" } }
%span
+ {{ overFlowSelectors().length }} more
%i.ofn-i_052-point-down
.f-dropdown.text-right.content{ ng: { attr: { id: "{{ 'show-more-' + selectorName }}" } } }
%ul
%active-selector{ ng: { repeat: "selector in overFlowSelectors()", hide: "selector.fits" } }
%render-svg{path: "{{selector.object.icon}}", ng: { if: "selector.object.icon"}}
%span {{ selector.object.name }}

View File

@@ -1,3 +0,0 @@
%active-selector{"ng-repeat" => "selector in selectors()"}
%render-svg{path: "{{selector.taxon.icon}}"}
%span {{ selector.taxon.name }}

View File

@@ -0,0 +1,3 @@
@import 'plugins/font-awesome';
.icon-refund:before { @extend .icon-ok:before }

View File

@@ -0,0 +1,120 @@
@import mixins
@import branding
@import big-input
@import animations
@mixin filter-selector($base-clr, $border-clr, $hover-clr)
&.inline-block, ul.inline-block
display: inline-block
li
display: inline-block
@include border-radius(0)
padding: 0
margin: 0 0 0.25rem 0.25rem
&:hover, &:focus
background: transparent
&.active
box-shadow: none
a, a.button
display: block
padding-top: 0.5rem
@include border-radius(0.5em)
border: 1px solid $border-clr
padding: 0.5em 0.625em
font-size: 0.875em
color: $base-clr
font-size: 0.75em
background: white
margin: 0
i
padding-left: 0.25rem
render-svg
&, & svg
width: 1rem
height: 1rem
float: left
padding-right: 0.25rem
path
@include csstrans
fill: $base-clr
&:hover, &:focus
border-color: $hover-clr
color: $hover-clr
render-svg
svg
path
fill: $hover-clr
&.disabled
opacity: 0.6
&:hover, &:focus
border-color: $border-clr
color: $base-clr
render-svg
svg
path
fill: $base-clr
&.active, &.active:hover, &.active:focus
border: 1px solid $base-clr
background: $base-clr
color: white
render-svg
svg
path
fill: white
// Alert when search, taxon, filter is triggered
.alert-box.search-alert
background-color: $clr-yellow-light
border-color: $clr-yellow-light
color: #777
font-size: 0.75rem
padding: 0.5rem 0.75rem
span.applied-properties
color: #333
span.applied-taxons
color: $clr-blue
span.applied-search
color: $clr-brick
span.filter-label
opacity: 0.75
.filter-shopfront.taxon-selectors, .filter-shopfront.property-selectors
background: transparent
single-line-selectors
overflow-x: hidden
white-space: nowrap
.f-dropdown
overflow-x: auto
white-space: normal
ul
margin: 0
ul, ul li
list-style: none
.filter-shopfront
// Shopfront taxons
&.taxon-selectors
@include filter-selector($clr-blue, $clr-blue-light, $clr-blue-bright)
// Shopfront properties
&.property-selectors
@include filter-selector(#666, #ccc, #777)

View File

@@ -9,8 +9,7 @@
@include placeholder(rgba(0,0,0,0.4), #777)
input#search
@include big-input(rgba(0,0,0,0.3), #777, $clr-brick)
@include big-input-static
@include medium-input(rgba(0,0,0,0.3), #777, $clr-brick)
// ordering
product

View File

@@ -0,0 +1,6 @@
.product-header
h1, h2, h3, h4, h5, h6
margin: 0
hr
margin: 0.5em 0

View File

@@ -30,20 +30,20 @@
text-decoration: underline
span.margin-top
margin-top: 0.5rem
margin-top: 0.5rem
display: inline-block
// Generic text resize
@media all and (max-width: 640px)
@media all and (max-width: 640px)
&, & *
font-size: 0.875rem
font-size: 0.875rem
fat > div label
&, & *
font-size: 0.75rem
&, & *
font-size: 0.75rem
.active_table_row // Inherits from active_table
border: 1px solid transparent
// Inherits from active_table
.active_table_row
border: 1px solid transparent
@include border-radius(0.5em)
// Foundation overrides
@@ -76,15 +76,15 @@
.active_table_row:last-child
border-bottom: 1px solid $disabled-bright
@include border-radius-mixed(0, 0, 0.5em, 0.5em)
//Open row sections
.fat > div
border-top: 1px solid #aaa
@media all and (max-width: 640px)
@media all and (max-width: 640px)
margin-top: 1em
ul, ol
ul, ol
font-size: 0.875rem
[class*="block-grid-"] > li
@@ -96,10 +96,10 @@
margin-top: 0.25rem
margin-bottom: 0.25rem
color: #777
p.trans-sentence
text-transform: capitalize
&.closed
&:hover, &:active, &:focus
.active_table_row.closed
@@ -112,7 +112,3 @@
&.open
.active_table_row:first-child
color: $dark-grey

View File

@@ -8,7 +8,7 @@
margin-left: 0
margin-right: 0
.row.filter-box:first-child, .row.filter-box.filter-box-shopfront
.row.filter-box:first-child
border: 1px solid $clr-blue-light
@include border-radius(0.25em)
margin-top: 2px
@@ -19,13 +19,9 @@
background: transparent
margin-top: 1em
.row.filter-box.filter-box-shopfront
margin-top: 0
products .filter-box
background: #f7f7f7
.filter-box
background: rgba(245,245,245,0.6)
.tdhead
@@ -40,7 +36,6 @@ products .filter-box
[class*="block-grid-"] > li
padding-bottom: 0.5rem !important
li
@include border-radius(12px)
padding-top: 0.5rem
@@ -105,16 +100,6 @@ products .filter-box
path
fill: #666
.filter-box.filter-box-shopfront
.tdhead
margin-top: 0rem
margin-bottom: 0.75rem
padding: 0.5rem 0
h5
color: $clr-blue
.button.tiny
margin-bottom: 0rem
.button.filterbtn
margin-bottom: 0 !important
min-width: 160px

View File

@@ -2,6 +2,8 @@
// ANIMATION FUNCTIONS
//
@-webkit-keyframes slideInDown
0%
opacity: 0
@@ -22,6 +24,8 @@
-ms-transform: translateY(0)
transform: translateY(0)
@-webkit-keyframes slideOutUp
0%
-webkit-transform: translateY(0)
@@ -160,6 +164,51 @@ product.animate-repeat
-webkit-animation-fill-mode: both
animation-fill-mode: both
//
.animate-slide
max-height: 500px
opacity: 1 !important
-webkit-transition: all 300ms ease-in-out
-moz-transition: all 300ms ease-in-out
-o-transition: all 300ms ease-in-out
transition: all 300ms ease-in-out
&.ng-hide
overflow: hidden
max-height: 0
opacity: 0 !important
// &.ng-hide-add-active, &.ng-hide-remove-active
&.ng-hide-add, &.ng-hide-remove
/* IMPORTANT: this needs to be here to make it visible during the animation
since the .ng-hide class is already on the element rendering
it as hidden. */
display: block !important
.animate-show
opacity: 1 !important
-webkit-transition: all 300ms ease-in-out
-moz-transition: all 300ms ease-in-out
-o-transition: all 300ms ease-in-out
transition: all 300ms ease-in-out
&.ng-hide
opacity: 0 !important
// &.ng-hide-add-active, &.ng-hide-remove-active
&.ng-hide-add, &.ng-hide-remove
/* IMPORTANT: this needs to be here to make it visible during the animation
since the .ng-hide class is already on the element rendering
it as hidden. */
display: block !important
@mixin csstrans
-webkit-transition: all 300ms ease

View File

@@ -13,7 +13,7 @@
border: 2px solid $input
font-size: 2rem
box-shadow: 0
padding: 0.75rem 1rem 0.35rem 1rem
padding: 0.75rem 1rem 0.35rem
height: auto
width: 100%
margin-bottom: 0.5rem
@@ -33,8 +33,9 @@
background: white
background: rgba(255,255,255,0.5)
text-shadow: 0 0 10px #ffffff
padding: 1.5rem 1rem 1rem 1rem
padding: 1.5rem 1rem 1rem
letter-spacing: 0.02rem
outline: none
@mixin big-input-static
outline: 0
@@ -42,6 +43,34 @@
padding: 0.75rem 1rem 0.35rem 1rem
letter-spacing: 0
@mixin medium-input($input, $inputhvr, $inputactv)
@include avenir
@include csstrans
@include border-radius(0.5rem)
background: rgba(255,255,255,0.1)
border: 2px solid $input
font-size: 0.875rem
box-shadow: 0
padding: 0.5rem 0.625rem 0.375rem
height: auto
width: 100%
margin-bottom: 0.5rem
box-shadow: none
color: $inputactv
&:hover
@include box-shadow(0 1px 1px 0 rgba(255,255,255,0.25))
border: 2px solid $inputhvr
color: $inputactv
&:active, &:focus, &.active
border: 2px solid $inputactv
color: $inputactv
background: white
background: rgba(255,255,255,0.5)
text-shadow: 0 0 10px #ffffff
outline: none
@mixin placeholder($placeholder, $placeholderhvr)
::-webkit-input-placeholder
color: $placeholder

View File

@@ -15,6 +15,8 @@ $clr-blue: #0096ad
$clr-blue-light: #85d9e5
$clr-blue-bright: #14b6cc
$clr-yellow-light: #faf6c7
$disabled-light: #e5e5e5
$disabled-bright: #ccc
$disabled-med: #b3b3b3
@@ -25,3 +27,4 @@ $med-drk-grey: #444
$dark-grey: #333
$light-grey: #ddd
$black: #000

View File

@@ -7,6 +7,11 @@
margin-bottom: 10px
outline: 1px solid #ccc
@include box-shadow(0 1px 2px 1px rgba(0,0,0,0.15))
// placeholder for when no product images
&.placeholder
opacity: 0.35
@media all and (max-width: 1024px)
display: none
.hero-img
outline: 1px solid $disabled-bright

View File

@@ -10,11 +10,12 @@
height: 100%
width: 100%
img // https://github.com/zurb/foundation/issues/112
// https://github.com/zurb/foundation/issues/112
img
max-width: none
height: auto
#pac-input
#pac-input
@include big-input(#888, #333, $clr-brick)
@include big-input-static
font-size: 1.5rem

View File

@@ -8,6 +8,7 @@ dialog, .reveal-modal
border-bottom: 30px solid white
overflow-y: scroll
overflow-x: hidden
min-height: 260px
// Not working yet - want a nice gradient shadow when there is overflow - needs JS too
// &:after
// @include elipse-shadow(0 0 40px rgba(0, 0, 0, 0.8))
@@ -32,6 +33,7 @@ dialog, .reveal-modal
.reveal-modal-bg
background-color: rgba(0,0,0,0.85)
position: fixed
dialog .close-reveal-modal, .reveal-modal .close-reveal-modal
right: 0.25rem

View File

@@ -15,10 +15,8 @@
products
display: block
padding-top: 2.3em
padding-top: 20px
@media all and (max-width: 768px)
padding-top: 1em
input.button.right
float: left

View File

@@ -20,21 +20,27 @@
right: 22px !important
left: auto
ul, li
list-style: none
margin-left: 0
table
width: 100%
border: none
border-spacing: 0px
margin-bottom: 5px
li
float: none
.row .columns
padding-left: 0.25rem
padding-right: 0.25rem
li.total-cart
background-color: #424242
li.product-cart
border-top: 1px solid #424242
tr.total-cart
color: #fff
background-color: #424242
td
color: #fff
tr.product-cart
background-color: #333333
border-top: 1px solid #424242
td
padding: 4px 12px
color: #fff
.buttons
.button
height: auto
top: 0px
// Shopping cart
#cart-detail

View File

@@ -20,6 +20,17 @@ module Admin
end
end
def for_order_cycle
respond_to do |format|
format.html
format.json do
render json: ActiveModel::ArraySerializer.new( @collection,
each_serializer: Api::Admin::EnterpriseFeeSerializer, controller: self
).to_json
end
end
end
def bulk_update
@enterprise_fee_set = EnterpriseFeeSet.new(params[:enterprise_fee_set])
if @enterprise_fee_set.save
@@ -63,9 +74,22 @@ module Admin
end
def collection
collection = EnterpriseFee.managed_by(spree_current_user).order('enterprise_id', 'fee_type', 'name')
collection = collection.for_enterprise(current_enterprise) if current_enterprise
collection
case action
when :for_order_cycle
order_cycle = OrderCycle.find_by_id(params[:order_cycle_id]) if params[:order_cycle_id]
coordinator = Enterprise.find_by_id(params[:coordinator_id]) if params[:coordinator_id]
order_cycle = OrderCycle.new(coordinator: coordinator) if order_cycle.nil? && coordinator.present?
enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, order_cycle).visible_enterprises
return EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
else
collection = EnterpriseFee.managed_by(spree_current_user).order('enterprise_id', 'fee_type', 'name')
collection = collection.for_enterprise(current_enterprise) if current_enterprise
collection
end
end
def collection_actions
[:index, :for_order_cycle]
end
def current_enterprise

View File

@@ -11,16 +11,15 @@ module Admin
before_filter :check_can_change_owner, only: :update
before_filter :check_can_change_bulk_owner, only: :bulk_update
before_filter :check_can_change_managers, only: :update
before_filter :strip_new_properties, only: [:create, :update]
before_filter :load_properties, only: [:edit, :update]
before_filter :setup_property, only: [:edit]
helper 'spree/products'
include ActionView::Helpers::TextHelper
include OrderCyclesHelper
def for_order_cycle
@collection = order_cycle_permitted_enterprises
end
def set_sells
enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
attributes = { sells: params[:sells] }
@@ -67,6 +66,16 @@ module Admin
end
end
def for_order_cycle
respond_to do |format|
format.json do
render json: ActiveModel::ArraySerializer.new( @collection,
each_serializer: Api::Admin::ForOrderCycle::EnterpriseSerializer, spree_current_user: spree_current_user
).to_json
end
end
end
protected
def build_resource_with_address
@@ -94,10 +103,18 @@ module Admin
end
def collection
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
OpenFoodNetwork::Permissions.new(spree_current_user).
editable_enterprises.
order('is_primary_producer ASC, name')
case action
when :for_order_cycle
order_cycle = OrderCycle.find_by_id(params[:order_cycle_id]) if params[:order_cycle_id]
coordinator = Enterprise.find_by_id(params[:coordinator_id]) if params[:coordinator_id]
order_cycle = OrderCycle.new(coordinator: coordinator) if order_cycle.nil? && coordinator.present?
return OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, order_cycle).visible_enterprises
else
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
OpenFoodNetwork::Permissions.new(spree_current_user).
editable_enterprises.
order('is_primary_producer ASC, name')
end
end
def collection_actions
@@ -132,8 +149,9 @@ module Admin
def override_sells
unless spree_current_user.admin?
has_hub = spree_current_user.enterprises.is_hub.any?
params[:enterprise][:sells] = has_hub ? 'any' : 'none'
has_hub = spree_current_user.owned_enterprises.is_hub.any?
new_enterprise_is_producer = Enterprise.new(params[:enterprise]).is_primary_producer
params[:enterprise][:sells] = (has_hub && !new_enterprise_is_producer) ? 'any' : 'none'
end
end
@@ -157,9 +175,27 @@ module Admin
end
end
def strip_new_properties
unless spree_current_user.admin? || params[:enterprise][:producer_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:enterprise][:producer_properties_attributes].each do |key, property|
params[:enterprise][:producer_properties_attributes].delete key unless names.include? property[:property_name]
end
end
end
def load_properties
@properties = Spree::Property.pluck(:name)
end
def setup_property
@enterprise.producer_properties.build
end
# Overriding method on Spree's resource controller
def location_after_save
if params[:enterprise].key? :producer_properties_attributes
refered_from_edit = URI(request.referer).path == main_app.edit_admin_enterprise_path(@enterprise)
if params[:enterprise].key?(:producer_properties_attributes) && !refered_from_edit
main_app.admin_enterprises_path
else
main_app.edit_admin_enterprise_path(@enterprise)

View File

@@ -1,24 +1,32 @@
require 'open_food_network/permissions'
require 'open_food_network/order_cycle_permissions'
require 'open_food_network/order_cycle_form_applicator'
module Admin
class OrderCyclesController < ResourceController
include OrderCyclesHelper
before_filter :load_order_cycle_set, :only => :index
before_filter :load_data_for_index, :only => :index
before_filter :require_coordinator, only: :new
before_filter :remove_protected_attrs, only: [:update]
before_filter :remove_unauthorized_bulk_attrs, only: [:bulk_update]
around_filter :protect_invalid_destroy, only: :destroy
def show
respond_to do |format|
format.html
format.json
format.json do
render json: Api::Admin::OrderCycleSerializer.new(@order_cycle, current_user: spree_current_user).to_json
end
end
end
def new
respond_to do |format|
format.html
format.json
format.json do
render json: Api::Admin::OrderCycleSerializer.new(@order_cycle, current_user: spree_current_user).to_json
end
end
end
@@ -27,7 +35,7 @@ module Admin
respond_to do |format|
if @order_cycle.save
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, order_cycle_permitted_enterprises).go!
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, spree_current_user).go!
flash[:notice] = 'Your order cycle has been created.'
format.html { redirect_to admin_order_cycles_path }
@@ -44,7 +52,7 @@ module Admin
respond_to do |format|
if @order_cycle.update_attributes(params[:order_cycle])
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, order_cycle_permitted_enterprises).go!
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, spree_current_user).go!
flash[:notice] = 'Your order cycle has been updated.'
format.html { redirect_to admin_order_cycles_path }
@@ -73,26 +81,27 @@ module Admin
protected
def collection
ocs = OrderCycle.managed_by(spree_current_user)
def collection(show_more=false)
ocs = OrderCycle.accessible_by(spree_current_user)
ocs.undated +
ocs.soonest_closing +
ocs.soonest_opening +
ocs.most_recently_closed
(show_more ? ocs.closed : ocs.recently_closed)
end
private
def load_order_cycle_set
@order_cycle_set = OrderCycleSet.new :collection => collection
def load_data_for_index
@show_more = !!params[:show_more]
@order_cycle_set = OrderCycleSet.new :collection => collection(@show_more)
end
def require_coordinator
if params[:coordinator_id] && @order_cycle.coordinator = order_cycle_coordinating_enterprises.find_by_id(params[:coordinator_id])
if params[:coordinator_id] && @order_cycle.coordinator = permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id])
return
end
available_coordinators = order_cycle_coordinating_enterprises.select(&:confirmed?)
available_coordinators = permitted_coordinating_enterprises_for(@order_cycle).select(&:confirmed?)
case available_coordinators.count
when 0
flash[:error] = "None of your enterprises have permission to coordinate an order cycle"
@@ -104,5 +113,31 @@ module Admin
render :set_coordinator
end
end
def protect_invalid_destroy
begin
yield
rescue ActiveRecord::InvalidForeignKey
redirect_to main_app.admin_order_cycles_url
flash[:error] = "That order cycle has been selected by a customer and cannot be deleted. To prevent customers from accessing it, please close it instead."
end
end
def remove_protected_attrs
params[:order_cycle].delete :coordinator_id
unless Enterprise.managed_by(spree_current_user).include?(@order_cycle.coordinator)
params[:order_cycle].delete_if{ |k,v| [:name, :orders_open_at, :orders_close_at].include? k.to_sym }
end
end
def remove_unauthorized_bulk_attrs
params[:order_cycle_set][:collection_attributes].each do |i, hash|
order_cycle = OrderCycle.find(hash[:id])
unless Enterprise.managed_by(spree_current_user).include?(order_cycle.andand.coordinator)
params[:order_cycle_set][:collection_attributes].delete i
end
end
end
end
end

View File

@@ -2,7 +2,6 @@ require 'open_food_network/spree_api_key_loader'
module Admin
class VariantOverridesController < ResourceController
include OrderCyclesHelper
include OpenFoodNetwork::SpreeApiKeyLoader
before_filter :load_spree_api_key, only: :index
@@ -35,7 +34,8 @@ module Admin
private
def load_data
@hubs = order_cycle_hub_enterprises
@hubs = OpenFoodNetwork::Permissions.new(spree_current_user).
variant_override_hubs.by_name
# Used in JS to look up the name of the producer of each product
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).

View File

@@ -13,7 +13,8 @@ module Api
end
def accessible
@enterprises = Enterprise.ransack(params[:q]).result.accessible_by(current_api_user)
permitted = OpenFoodNetwork::Permissions.new(current_api_user).order_cycle_enterprises
@enterprises = permitted.ransack(params[:q]).result
render params[:template] || :bulk_index
end
@@ -63,7 +64,9 @@ module Api
end
def override_sells
params[:enterprise][:sells] = 'unspecified'
has_hub = current_api_user.owned_enterprises.is_hub.any?
new_enterprise_is_producer = !!params[:enterprise][:is_primary_producer]
params[:enterprise][:sells] = (has_hub && !new_enterprise_is_producer) ? 'any' : 'unspecified'
end
def override_visible

View File

@@ -9,7 +9,16 @@ module Api
end
def accessible
@order_cycles = OrderCycle.ransack(params[:q]).result.accessible_by(current_api_user)
@order_cycles = if params[:as] == "distributor"
OrderCycle.ransack(params[:q]).result.
involving_managed_distributors_of(current_api_user).order('updated_at DESC')
elsif params[:as] == "producer"
OrderCycle.ransack(params[:q]).result.
involving_managed_producers_of(current_api_user).order('updated_at DESC')
else
OrderCycle.ransack(params[:q]).result.accessible_by(current_api_user)
end
render params[:template] || :bulk_index
end
end

View File

@@ -8,15 +8,12 @@ class ApplicationController < ActionController::Base
super(options, response_status)
end
def after_sign_in_path_for(resource)
def set_checkout_redirect
if request.referer and referer_path = URI(request.referer).path
[main_app.checkout_path].include?(referer_path) ? referer_path : root_path
else
root_path
session["spree_user_return_to"] = [main_app.checkout_path].include?(referer_path) ? referer_path : root_path
end
end
private
def require_distributor_chosen

View File

@@ -19,6 +19,7 @@ class CheckoutController < Spree::CheckoutController
def update
if @order.update_attributes(object_params)
check_order_for_phantom_fees
fire_event('spree.checkout.update')
while @order.state != "complete"
if @order.state == "payment"
@@ -58,6 +59,20 @@ class CheckoutController < Spree::CheckoutController
private
def check_order_for_phantom_fees
phantom_fees = @order.adjustments.joins('LEFT OUTER JOIN spree_line_items ON spree_line_items.id = spree_adjustments.source_id').
where("originator_type = 'EnterpriseFee' AND source_type = 'Spree::LineItem' AND spree_line_items.id IS NULL")
if phantom_fees.any?
Bugsnag.notify(RuntimeError.new("Phantom Fees"), {
phantom_fees: {
phantom_total: phantom_fees.sum(&:amount).to_s,
phantom_fees: phantom_fees.as_json
}
})
end
end
# Copied and modified from spree. Remove check for order state, since the state machine is
# progressed all the way in one go with the one page checkout.
def object_params
@@ -110,7 +125,7 @@ class CheckoutController < Spree::CheckoutController
last_used_bill_address, last_used_ship_address = find_last_used_addresses(@order.email)
preferred_bill_address, preferred_ship_address = spree_current_user.bill_address, spree_current_user.ship_address if spree_current_user.respond_to?(:bill_address) && spree_current_user.respond_to?(:ship_address)
@order.bill_address ||= preferred_bill_address || last_used_bill_address || Spree::Address.default
@order.ship_address ||= preferred_ship_address || last_used_ship_address || Spree::Address.default
@order.ship_address ||= preferred_ship_address || last_used_ship_address || Spree::Address.default
end
def after_payment

View File

@@ -32,6 +32,24 @@ class EnterpriseConfirmationsController < DeviseController
set_flash_message(:error, :not_confirmed) if is_navigational_format?
end
respond_with_navigational(resource){ redirect_to spree.admin_path }
respond_with_navigational(resource){ redirect_to redirect_path(resource) }
end
end
private
def new_user_reset_path(resource)
password = Devise.friendly_token.first(8)
user = Spree::User.create(email: resource.email, password: password, password_confirmation: password)
user.send_reset_password_instructions
resource.users << user
spree.edit_spree_user_password_path(user, :reset_password_token => user.reset_password_token, return_to: spree.admin_path)
end
def redirect_path(resource)
if resource.persisted? && !Spree::User.exists?(email: resource.email)
new_user_reset_path(resource)
else
spree.admin_path
end
end
end

View File

@@ -0,0 +1,8 @@
Spree::Admin::LineItemsController.class_eval do
private
def load_order
@order = Spree::Order.find_by_number!(params[:order_id])
authorize! :update, @order
end
end

View File

@@ -9,6 +9,13 @@ Spree::Admin::OrdersController.class_eval do
# in an auth failure as the @order object is nil for collection actions
before_filter :check_authorization, :except => :bulk_management
# After updating an order, the fees should be updated as well
# Currently, adding or deleting line items does not trigger updating the
# fees! This is a quick fix for that.
# TODO: update fees when adding/removing line items
# instead of the update_distribution_charge method.
after_filter :update_distribution_charge, :only => :update
respond_override :index => { :html =>
{ :success => lambda {
# Filter orders to only show those distributed by current user (or all for admin user)
@@ -17,4 +24,17 @@ Spree::Admin::OrdersController.class_eval do
page(params[:page]).
per(params[:per_page] || Spree::Config[:orders_per_page])
} } }
# Overwrite to use confirm_email_for_customer instead of confirm_email.
# This uses a new template. See mailers/spree/order_mailer_decorator.rb.
def resend
Spree::OrderMailer.confirm_email_for_customer(@order.id, true).deliver
flash[:success] = t(:order_email_resent)
respond_with(@order) { |format| format.html { redirect_to :back } }
end
def update_distribution_charge
@order.update_distribution_charge!
end
end

View File

@@ -5,6 +5,7 @@ Spree::Admin::ProductsController.class_eval do
include OrderCyclesHelper
before_filter :load_form_data, :only => [:bulk_edit, :new, :create, :edit, :update]
before_filter :load_spree_api_key, :only => [:bulk_edit, :variant_overrides]
before_filter :strip_new_properties, only: [:create, :update]
alias_method :location_after_save_original, :location_after_save
@@ -95,4 +96,13 @@ Spree::Admin::ProductsController.class_eval do
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).managed_product_enterprises.is_primary_producer.by_name
@taxons = Spree::Taxon.order(:name)
end
def strip_new_properties
unless spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:product][:product_properties_attributes].each do |key, property|
params[:product][:product_properties_attributes].delete key unless names.include? property[:property_name]
end
end
end
end

View File

@@ -102,7 +102,7 @@ Spree::Admin::ReportsController.class_eval do
send_data csv_string, :filename => "orders_and_distributors_#{timestamp}.csv"
end
end
def sales_tax
params[:q] ||= {}
@@ -323,7 +323,7 @@ Spree::Admin::ReportsController.class_eval do
sort_by: proc { |payment_state| payment_state } },
{ group_by: proc { |payment| payment.order.distributor },
sort_by: proc { |distributor| distributor.name } },
{ group_by: proc { |payment| payment.payment_method },
{ group_by: proc { |payment| Spree::PaymentMethod.unscoped { payment.payment_method } },
sort_by: proc { |method| method.name } } ]
when "itemised_payment_totals"
@@ -406,27 +406,34 @@ Spree::Admin::ReportsController.class_eval do
end
params[:q][:meta_sort] ||= "completed_at.desc"
# -- Search
@search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q])
orders = @search.result
@line_items = orders.map do |o|
lis = o.line_items.managed_by(spree_current_user)
lis = lis.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present?
lis
end.flatten
#payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments
permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
# -- Prepare form options
my_distributors = Enterprise.is_distributor.managed_by(spree_current_user)
my_suppliers = Enterprise.is_primary_producer.managed_by(spree_current_user)
# -- Search
@search = Spree::Order.complete.not_state(:canceled).search(params[:q])
orders = permissions.visible_orders.merge(@search.result)
@line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders))
@line_items = @line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present?
line_items_with_hidden_details = @line_items.where('"spree_line_items"."id" NOT IN (?)', permissions.editable_line_items)
@line_items.select{ |li| line_items_with_hidden_details.include? li }.each do |line_item|
# TODO We should really be hiding customer code here too, but until we
# have an actual association between order and customer, it's a bit tricky
line_item.order.bill_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil)
line_item.order.ship_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil)
line_item.order.assign_attributes(email: "HIDDEN")
end
# My distributors and any distributors distributing products I supply
@distributors = my_distributors | Enterprise.with_distributed_products_outer.merge(Spree::Product.in_any_supplier(my_suppliers))
@distributors = permissions.visible_enterprises_for_order_reports.is_distributor
# My suppliers and any suppliers supplying products I distribute
@suppliers = my_suppliers | my_distributors.map { |d| Spree::Product.in_distributor(d) }.flatten.map(&:supplier).uniq
@suppliers = permissions.visible_enterprises_for_order_reports.is_primary_producer
@order_cycles = OrderCycle.active_or_complete.
involving_managed_distributors_of(spree_current_user).order('orders_close_at DESC')
@order_cycles = OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC')
@report_types = REPORT_TYPES[:orders_and_fulfillment]
@report_type = params[:report_type]
@@ -525,18 +532,26 @@ Spree::Admin::ReportsController.class_eval do
table_items = @line_items
@include_blank = 'All'
header = ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant", "Amount", "Item (#{currency_symbol})", "Item + Fees (#{currency_symbol})", "Dist (#{currency_symbol})", "Ship (#{currency_symbol})", "Total (#{currency_symbol})", "Paid?",
"Shipping", "Delivery?", "Ship street", "Ship street 2", "Ship city", "Ship postcode", "Ship state", "Order notes"]
header = ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant",
"Amount", "Item (#{currency_symbol})", "Item + Fees (#{currency_symbol})", "Admin & Handling (#{currency_symbol})", "Ship (#{currency_symbol})", "Total (#{currency_symbol})", "Paid?",
"Shipping", "Delivery?",
"Ship Street", "Ship Street 2", "Ship City", "Ship Postcode", "Ship State",
"Comments", "SKU",
"Order Cycle", "Payment Method", "Customer Code", "Tags",
"Billing Street 1", "Billing Street 2", "Billing City", "Billing Postcode", "Billing State"
]
rsa = proc { |line_items| line_items.first.order.shipping_method.andand.require_ship_address }
columns = [ proc { |line_items| line_items.first.order.distributor.name },
columns = [
proc { |line_items| line_items.first.order.distributor.name },
proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname },
proc { |line_items| line_items.first.order.email },
proc { |line_items| line_items.first.order.bill_address.phone },
proc { |line_items| line_items.first.variant.product.supplier.name },
proc { |line_items| line_items.first.variant.product.name },
proc { |line_items| line_items.first.variant.full_name },
proc { |line_items| line_items.sum { |li| li.quantity } },
proc { |line_items| line_items.sum { |li| li.amount } },
proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } },
@@ -547,25 +562,40 @@ Spree::Admin::ReportsController.class_eval do
proc { |line_items| line_items.first.order.shipping_method.andand.name },
proc { |line_items| rsa.call(line_items) ? 'Y' : 'N' },
proc { |line_items| line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) },
proc { |line_items| line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) },
proc { |line_items| line_items.first.order.ship_address.andand.city if rsa.call(line_items) },
proc { |line_items| line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) },
proc { |line_items| line_items.first.order.ship_address.andand.state if rsa.call(line_items) },
proc { |line_items| line_items.first.order.special_instructions }]
proc { |line_items| "" },
proc { |line_items| line_items.first.variant.product.sku },
proc { |line_items| line_items.first.order.order_cycle.andand.name },
proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name },
proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.code },
proc { |line_items| "" },
proc { |line_items| line_items.first.order.bill_address.andand.address1 },
proc { |line_items| line_items.first.order.bill_address.andand.address2 },
proc { |line_items| line_items.first.order.bill_address.andand.city },
proc { |line_items| line_items.first.order.bill_address.andand.zipcode },
proc { |line_items| line_items.first.order.bill_address.andand.state } ]
rules = [ { group_by: proc { |line_item| line_item.order.distributor },
sort_by: proc { |distributor| distributor.name } },
{ group_by: proc { |line_item| line_item.order },
sort_by: proc { |order| order.bill_address.lastname + " " + order.bill_address.firstname },
summary_columns: [ proc { |line_items| line_items.first.order.distributor.name },
summary_columns: [
proc { |line_items| line_items.first.order.distributor.name },
proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "TOTAL" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| line_items.sum { |li| li.amount } },
proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } },
@@ -576,13 +606,27 @@ Spree::Admin::ReportsController.class_eval do
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" } ] },
proc { |line_items| line_items.first.order.special_instructions } ,
proc { |line_items| "" },
proc { |line_items| line_items.first.order.order_cycle.andand.name },
proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" },
proc { |line_items| "" }
] },
{ group_by: proc { |line_item| line_item.variant.product },
sort_by: proc { |product| product.name } },

View File

@@ -6,15 +6,18 @@ Spree::Admin::VariantsController.class_eval do
@variants = Spree::Variant.ransack(search_params.merge(:m => 'or')).result
if params[:distributor_id].present?
distributor = Enterprise.find params[:distributor_id]
@variants = @variants.in_distributor(distributor)
end
if params[:order_cycle_id].present?
order_cycle = OrderCycle.find params[:order_cycle_id]
@variants = @variants.in_order_cycle(order_cycle)
end
if params[:distributor_id].present?
distributor = Enterprise.find params[:distributor_id]
@variants = @variants.in_distributor(distributor)
# Perform scoping after all filtering is done.
# Filtering could be a problem on scoped variants.
@variants.each { |v| v.scope_to_hub(distributor) }
end
end
def destroy

View File

@@ -20,15 +20,6 @@ Spree::Api::ProductsController.class_eval do
render_paged_products @products
end
def distributable
producers = OpenFoodNetwork::Permissions.new(current_api_user).
order_cycle_enterprises.is_primary_producer.by_name
@products = paged_products_for_producers producers
render_paged_products @products
end
def overridable
producers = OpenFoodNetwork::Permissions.new(current_api_user).
variant_override_producers.by_name
@@ -74,7 +65,7 @@ Spree::Api::ProductsController.class_eval do
end
def render_paged_products(products)
render text: { products: ActiveModel::ArraySerializer.new(products, each_serializer: Spree::Api::ProductSerializer), pages: products.num_pages }.to_json
render text: { products: ActiveModel::ArraySerializer.new(products, each_serializer: Api::Admin::ProductSerializer), pages: products.num_pages }.to_json
end
end

View File

@@ -1,4 +1,6 @@
Spree::UserSessionsController.class_eval do
before_filter :set_checkout_redirect, only: :create
def create
authenticate_spree_user!

View File

@@ -1,6 +1,8 @@
class UserPasswordsController < Spree::UserPasswordsController
layout 'darkswarm'
before_filter :set_admin_redirect, only: :edit
def create
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
@@ -18,4 +20,10 @@ class UserPasswordsController < Spree::UserPasswordsController
end
end
end
private
def set_admin_redirect
session["spree_user_return_to"] = params[:return_to] if params[:return_to]
end
end

View File

@@ -1,4 +1,5 @@
class UserRegistrationsController < Spree::UserRegistrationsController
before_filter :set_checkout_redirect, only: :create
# POST /resource/sign_up
def create

View File

@@ -47,7 +47,7 @@ module Admin
end
def admin_inject_products
admin_inject_json_ams_array "ofn.admin", "products", @products, Spree::Api::ProductSerializer
admin_inject_json_ams_array "ofn.admin", "products", @products, Api::Admin::ProductSerializer
end
def admin_inject_taxons

View File

@@ -18,20 +18,24 @@ module CheckoutHelper
end
def display_checkout_admin_and_handling_adjustments_total_for(order)
adjustments = order.adjustments.eligible.where('originator_type = ? AND source_type != ? ', 'EnterpriseFee', 'Spree::LineItem' )
Spree::Money.new( adjustments.sum( &:amount ) , { :currency => order.currency })
adjustments = order.adjustments.eligible.where('originator_type = ? AND source_type != ? ', 'EnterpriseFee', 'Spree::LineItem')
Spree::Money.new adjustments.sum(&:amount) , currency: order.currency
end
def checkout_line_item_adjustments(order)
order.adjustments.eligible.where( source_type: "Spree::LineItem")
order.adjustments.eligible.where(source_type: "Spree::LineItem")
end
def checkout_subtotal(order)
order.item_total + checkout_line_item_adjustments(order).sum( &:amount )
order.item_total + checkout_line_item_adjustments(order).sum(&:amount)
end
def display_checkout_subtotal(order)
Spree::Money.new( checkout_subtotal(order) , { :currency => order.currency })
Spree::Money.new checkout_subtotal(order) , currency: order.currency
end
def display_checkout_tax_total(order)
Spree::Money.new order.total_tax, currency: order.currency
end
def checkout_state_options(source_address)

View File

@@ -21,6 +21,10 @@ module InjectionHelper
inject_json_ams "taxons", Spree::Taxon.all, Api::TaxonSerializer
end
def inject_properties
inject_json_ams "properties", Spree::Property.all, Api::IdNameSerializer
end
def inject_currency_config
inject_json_ams "currencyConfig", {}, Api::CurrencyConfigSerializer
end

View File

@@ -3,36 +3,32 @@ module OrderCyclesHelper
@current_order_cycle ||= current_order(false).andand.order_cycle
end
def order_cycle_permitted_in(enterprises)
enterprises.merge(order_cycle_permitted_enterprises)
def permitted_enterprises_for(order_cycle)
OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, order_cycle).visible_enterprises
end
def order_cycle_permitted_enterprises
OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_enterprises
def permitted_producer_enterprises_for(order_cycle)
permitted_enterprises_for(order_cycle).is_primary_producer.by_name
end
def order_cycle_producer_enterprises
order_cycle_permitted_enterprises.is_primary_producer.by_name
def permitted_producer_enterprise_options_for(order_cycle)
validated_enterprise_options permitted_producer_enterprises_for(order_cycle), confirmed: true
end
def order_cycle_producer_enterprise_options
validated_enterprise_options order_cycle_producer_enterprises, confirmed: true
def permitted_coordinating_enterprises_for(order_cycle)
Enterprise.managed_by(spree_current_user).is_distributor.by_name
end
def order_cycle_coordinating_enterprises
order_cycle_permitted_enterprises.is_distributor.by_name
def permitted_coordinating_enterprise_options_for(order_cycle)
validated_enterprise_options permitted_coordinating_enterprises_for(order_cycle), confirmed: true
end
def order_cycle_coordinating_enterprise_options
validated_enterprise_options order_cycle_coordinating_enterprises, confirmed: true
def permitted_hub_enterprises_for(order_cycle)
permitted_enterprises_for(order_cycle).is_hub.by_name
end
def order_cycle_hub_enterprises
order_cycle_permitted_enterprises.is_hub.by_name
end
def order_cycle_hub_enterprise_options
validated_enterprise_options order_cycle_hub_enterprises, confirmed: true, shipping_and_payment_methods: true
def permitted_hub_enterprise_options_for(order_cycle)
validated_enterprise_options permitted_hub_enterprises_for(order_cycle), confirmed: true, shipping_and_payment_methods: true
end
def order_cycle_status_class(order_cycle)
@@ -79,6 +75,14 @@ module OrderCyclesHelper
order_cycle.exchanges.to_enterprises(current_distributor).outgoing.first.pickup_time
end
def can_delete?(order_cycle)
Spree::Order.where(order_cycle_id: order_cycle).none?
end
def viewing_as_coordinator_of?(order_cycle)
Enterprise.managed_by(spree_current_user).include? order_cycle.coordinator
end
private
def validated_enterprise_options(enterprises, options={})

View File

@@ -0,0 +1,6 @@
ConfirmOrderJob = Struct.new(:order_id) do
def perform
Spree::OrderMailer.confirm_email_for_customer(order_id).deliver
Spree::OrderMailer.confirm_email_for_shop(order_id).deliver
end
end

View File

@@ -0,0 +1,6 @@
ConfirmSignupJob = Struct.new(:user_id) do
def perform
user = Spree::User.find user_id
Spree::UserMailer.signup_confirmation(user).deliver
end
end

View File

@@ -0,0 +1,6 @@
WelcomeEnterpriseJob = Struct.new(:enterprise_id) do
def perform
enterprise = Enterprise.find enterprise_id
EnterpriseMailer.welcome(enterprise).deliver
end
end

View File

@@ -1,7 +1,10 @@
class Customer < ActiveRecord::Base
belongs_to :enterprise
belongs_to :user, :class_name => Spree.user_class
validates :code, presence: true, uniqueness: {scope: :enterprise_id}
validates :email, presence: true
validates :enterprise_id, presence: true
scope :of, ->(enterprise) { where(enterprise_id: enterprise) }
end

View File

@@ -8,6 +8,8 @@ class Enterprise < ActiveRecord::Base
preference :shopfront_taxon_order, :string, default: ""
devise :confirmable, reconfirmable: true, confirmation_keys: [ :id, :email ]
handle_asynchronously :send_confirmation_instructions
handle_asynchronously :send_on_create_confirmation_instructions
self.inheritance_column = nil
@@ -15,6 +17,7 @@ class Enterprise < ActiveRecord::Base
has_and_belongs_to_many :groups, class_name: 'EnterpriseGroup'
has_many :producer_properties, foreign_key: 'producer_id'
has_many :properties, through: :producer_properties
has_many :supplied_products, :class_name => 'Spree::Product', :foreign_key => 'supplier_id', :dependent => :destroy
has_many :distributed_orders, :class_name => 'Spree::Order', :foreign_key => 'distributor_id'
belongs_to :address, :class_name => 'Spree::Address'
@@ -76,7 +79,7 @@ class Enterprise < ActiveRecord::Base
after_rollback :restore_permalink
scope :by_name, order('name')
scope :visible, where(:visible => true)
scope :visible, where(visible: true)
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :unconfirmed, where('confirmed_at IS NULL')
scope :activated, where("confirmed_at IS NOT NULL AND sells != 'unspecified'")
@@ -114,6 +117,9 @@ class Enterprise < ActiveRecord::Base
scope :with_distributed_products_outer,
joins('LEFT OUTER JOIN product_distributions ON product_distributions.distributor_id = enterprises.id').
joins('LEFT OUTER JOIN spree_products ON spree_products.id = product_distributions.product_id')
scope :with_order_cycles_as_supplier_outer,
joins("LEFT OUTER JOIN exchanges ON (exchanges.sender_id = enterprises.id AND exchanges.incoming = 't')").
joins('LEFT OUTER JOIN order_cycles ON (order_cycles.id = exchanges.order_cycle_id)')
scope :with_order_cycles_as_distributor_outer,
joins("LEFT OUTER JOIN exchanges ON (exchanges.receiver_id = enterprises.id AND exchanges.incoming = 'f')").
joins('LEFT OUTER JOIN order_cycles ON (order_cycles.id = exchanges.order_cycle_id)')
@@ -156,17 +162,6 @@ class Enterprise < ActiveRecord::Base
end
}
# Return enterprises that participate in order cycles that user coordinates, sends to or receives from
scope :accessible_by, lambda { |user|
if user.has_spree_role?('admin')
scoped
else
with_order_cycles_outer.
where('order_cycles.id IN (?)', OrderCycle.accessible_by(user)).
select('DISTINCT enterprises.*')
end
}
def self.find_near(suburb)
enterprises = []
@@ -316,6 +311,11 @@ class Enterprise < ActiveRecord::Base
end
end
# Based on a devise method, but without adding errors
def pending_any_confirmation?
!confirmed? || pending_reconfirmation?
end
protected
def devise_mailer
@@ -344,7 +344,7 @@ class Enterprise < ActiveRecord::Base
end
def send_welcome_email
EnterpriseMailer.welcome(self).deliver
Delayed::Job.enqueue WelcomeEnterpriseJob.new(self.id)
end
def strip_url(url)
@@ -378,13 +378,12 @@ class Enterprise < ActiveRecord::Base
enterprises = owner.owned_enterprises.where('enterprises.id != ?', self)
# We grant permissions to all pre-existing hubs
hub_permissions = [:add_to_order_cycle]
hub_permissions << :create_variant_overrides if is_primary_producer
enterprises.is_hub.each do |enterprise|
EnterpriseRelationship.create!(parent: self,
child: enterprise,
permissions_list: [:add_to_order_cycle,
:manage_products,
:edit_profile,
:create_variant_overrides])
permissions_list: hub_permissions)
end
# All pre-existing producers grant permission to new hubs
@@ -393,8 +392,6 @@ class Enterprise < ActiveRecord::Base
EnterpriseRelationship.create!(parent: enterprise,
child: self,
permissions_list: [:add_to_order_cycle,
:manage_products,
:edit_profile,
:create_variant_overrides])
end
end

View File

@@ -20,6 +20,7 @@ class EnterpriseFee < ActiveRecord::Base
scope :for_enterprise, lambda { |enterprise| where(enterprise_id: enterprise) }
scope :for_enterprises, lambda { |enterprises| where(enterprise_id: enterprises) }
scope :managed_by, lambda { |user|
if user.has_spree_role?('admin')

View File

@@ -28,4 +28,8 @@ class EnterpriseRelationship < ActiveRecord::Base
def permissions_list=(perms)
perms.andand.each { |name| permissions.build name: name }
end
def has_permission?(name)
permissions.map(&:name).map(&:to_sym).include? name.to_sym
end
end

View File

@@ -22,6 +22,7 @@ class Exchange < ActiveRecord::Base
scope :to_enterprise, lambda { |enterprise| where(receiver_id: enterprise) }
scope :from_enterprises, lambda { |enterprises| where('exchanges.sender_id IN (?)', enterprises) }
scope :to_enterprises, lambda { |enterprises| where('exchanges.receiver_id IN (?)', enterprises) }
scope :involving, lambda { |enterprises| where('exchanges.receiver_id IN (?) OR exchanges.sender_id IN (?)', enterprises, enterprises).select('DISTINCT exchanges.*') }
scope :supplying_to, lambda { |distributor| where('exchanges.incoming OR exchanges.receiver_id = ?', distributor) }
scope :with_variant, lambda { |variant| joins(:exchange_variants).where('exchange_variants.variant_id = ?', variant) }
scope :with_any_variant, lambda { |variants| joins(:exchange_variants).where('exchange_variants.variant_id IN (?)', variants).select('DISTINCT exchanges.*') }

View File

@@ -19,7 +19,14 @@ class OrderCycle < ActiveRecord::Base
scope :undated, where(orders_open_at: nil, orders_close_at: nil)
scope :soonest_closing, lambda { active.order('order_cycles.orders_close_at ASC') }
# TODO This method returns all the closed orders. So maybe we can replace it with :recently_closed.
scope :most_recently_closed, lambda { closed.order('order_cycles.orders_close_at DESC') }
scope :recently_closed, -> {
closed.
where("order_cycles.orders_close_at >= ?", 31.days.ago).
order("order_cycles.orders_close_at DESC") }
scope :soonest_opening, lambda { upcoming.order('order_cycles.orders_open_at ASC') }
scope :distributing_product, lambda { |product|
@@ -57,6 +64,23 @@ class OrderCycle < ActiveRecord::Base
joins('LEFT OUTER JOIN enterprises ON (enterprises.id = exchanges.sender_id OR enterprises.id = exchanges.receiver_id)')
}
scope :involving_managed_distributors_of, lambda { |user|
enterprises = Enterprise.managed_by(user)
# Order cycles where I managed an enterprise at either end of an outgoing exchange
# ie. coordinator or distibutor
joins(:exchanges).merge(Exchange.outgoing).
where('exchanges.receiver_id IN (?) OR exchanges.sender_id IN (?)', enterprises, enterprises)
}
scope :involving_managed_producers_of, lambda { |user|
enterprises = Enterprise.managed_by(user)
# Order cycles where I managed an enterprise at either end of an incoming exchange
# ie. coordinator or producer
joins(:exchanges).merge(Exchange.incoming).
where('exchanges.receiver_id IN (?) OR exchanges.sender_id IN (?)', enterprises, enterprises)
}
def self.first_opening_for(distributor)
with_distributor(distributor).soonest_opening.first

View File

@@ -8,6 +8,7 @@ class AbilityDecorator
add_enterprise_management_abilities user if can_manage_enterprises? user
add_group_management_abilities user if can_manage_groups? user
add_product_management_abilities user if can_manage_products? user
add_order_cycle_management_abilities user if can_manage_order_cycles? user
add_order_management_abilities user if can_manage_orders? user
add_relationship_management_abilities user if can_manage_relationships? user
end
@@ -33,6 +34,13 @@ class AbilityDecorator
user.enterprises.any? { |e| e.category != :hub_profile && e.producer_profile_only != true }
end
# Users can manage order cycles if they manage a sells own/any enterprise
# OR if they manage a producer which is included in any order cycles
def can_manage_order_cycles?(user)
can_manage_orders?(user) ||
OrderCycle.accessible_by(user).any?
end
# Users can manage orders if they have a sells own/any enterprise.
def can_manage_orders?(user)
( user.enterprises.map(&:sells) & %w(own any) ).any?
@@ -95,7 +103,7 @@ class AbilityDecorator
can [:admin, :index, :read, :update, :bulk_update], VariantOverride do |vo|
hub_auth = OpenFoodNetwork::Permissions.new(user).
order_cycle_enterprises.is_distributor.
variant_override_hubs.
include? vo.hub
producer_auth = OpenFoodNetwork::Permissions.new(user).
@@ -112,7 +120,18 @@ class AbilityDecorator
can [:admin, :index, :read, :create, :edit], Spree::Classification
# Reports page
can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], :report
can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management], :report
end
def add_order_cycle_management_abilities(user)
can [:admin, :index, :read, :edit, :update], OrderCycle do |order_cycle|
OrderCycle.accessible_by(user).include? order_cycle
end
can [:bulk_update, :clone, :destroy], OrderCycle do |order_cycle|
user.enterprises.include? order_cycle.coordinator
end
can [:for_order_cycle], Enterprise
can [:for_order_cycle], EnterpriseFee
end
def add_order_management_abilities(user)
@@ -125,17 +144,29 @@ class AbilityDecorator
end
can [:admin, :bulk_management], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor)
can [:admin, :create], Spree::LineItem
can [:destroy], Spree::LineItem do |item|
user.admin? || user.enterprises.include?(order.distributor) || user == order.order_cycle.manager
end
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
can [:destroy], Spree::Adjustment do |adjustment|
# Sharing code with destroying a line item. This should be unified and probably applied for other actions as well.
binding.pry
if user.admin?
true
elsif adjustment.adjustable.instance_of? Spree::Order
order = adjustment.adjustable
user.enterprises.include?(order.distributor) || user == order.order_cycle.manager
elsif adjustment.adjustable.instance_of? Spree::LineItem
order = adjustment.adjustable.order
user.enterprises.include?(order.distributor) || user == order.order_cycle.manager
end
end
can [:create], OrderCycle
can [:admin, :index, :read, :edit, :update, :bulk_update, :clone], OrderCycle do |order_cycle|
user.enterprises.include? order_cycle.coordinator
end
can [:for_order_cycle], Enterprise
can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant
can [:admin, :index, :read, :create, :edit, :update], Exchange

View File

@@ -26,6 +26,7 @@ Spree::LineItem.class_eval do
def price_with_adjustments
# EnterpriseFee#create_locked_adjustment applies adjustments on line items to their parent order,
# so line_item.adjustments returns an empty array
return 0 if quantity == 0
(price + order.adjustments.where(source_id: id).sum(&:amount) / quantity).round(2)
end

View File

@@ -103,13 +103,17 @@ Spree::Order.class_eval do
def add_variant(variant, quantity = 1, max_quantity = nil, currency = nil)
line_items(:reload)
current_item = find_line_item_by_variant(variant)
if current_item
Bugsnag.notify(RuntimeError.new("Order populator weirdness"), {
# Notify bugsnag if we get line items with a quantity of zero
if quantity == 0
Bugsnag.notify(RuntimeError.new("Zero Quantity Line Item"), {
current_item: current_item.as_json,
line_items: line_items.map(&:id),
reloaded: line_items(:reload).map(&:id),
variant: variant.as_json
})
end
if current_item
current_item.quantity = quantity
current_item.max_quantity = max_quantity
@@ -194,20 +198,37 @@ Spree::Order.class_eval do
end
end
# Does this order have shipments that can be shipped?
def ready_to_ship?
self.shipments.any?{|s| s.can_ship?}
end
# Ship all pending orders
def ship
self.shipments.each do |s|
s.ship if s.can_ship?
end
end
def available_shipping_methods(display_on = nil)
Spree::ShippingMethod.all_available(self, display_on)
end
def shipping_tax
adjustments(:reload).shipping.sum &:included_tax
end
def enterprise_fee_tax
adjustments(:reload).enterprise_fee.sum &:included_tax
end
def total_tax
(adjustments + price_adjustments).sum &:included_tax
end
# Overrride of Spree method, that allows us to send separate confirmation emails to user and shop owners
def deliver_order_confirmation_email
begin
Spree::OrderMailer.confirm_email_for_customer(self.id).deliver
Spree::OrderMailer.confirm_email_for_shop(self.id).deliver
rescue Exception => e
Bugsnag.notify(e)
logger.error("#{e.class.name}: #{e.message}")
logger.error(e.backtrace * "\n")
end
Delayed::Job.enqueue ConfirmOrderJob.new(id)
end

View File

@@ -0,0 +1,52 @@
module Spree
Payment.class_eval do
# Pin payments lacks void and credit methods, but it does have refund
# Here we swap credit out for refund and remove void as a possible action
def actions_with_pin_payment_adaptations
actions = actions_without_pin_payment_adaptations
if payment_method.is_a? Gateway::Pin
actions << 'refund' if actions.include? 'credit'
actions.reject! { |a| ['credit', 'void'].include? a }
end
actions
end
alias_method_chain :actions, :pin_payment_adaptations
def refund!(refund_amount=nil)
protect_from_connection_error do
check_environment
refund_amount = calculate_refund_amount(refund_amount)
if payment_method.payment_profiles_supported?
response = payment_method.refund((refund_amount * 100).round, source, response_code, gateway_options)
else
response = payment_method.refund((refund_amount * 100).round, response_code, gateway_options)
end
record_response(response)
if response.success?
self.class.create({ :order => order,
:source => self,
:payment_method => payment_method,
:amount => refund_amount.abs * -1,
:response_code => response.authorization,
:state => 'completed' }, :without_protection => true)
else
gateway_error(response)
end
end
end
private
def calculate_refund_amount(refund_amount=nil)
refund_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
refund_amount.to_f
end
end
end

View File

@@ -18,14 +18,16 @@ Spree::Product.class_eval do
delegate_belongs_to :master, :unit_value, :unit_description
delegate :images_attributes=, :display_as=, to: :master
attr_accessible :supplier_id, :primary_taxon_id, :distributor_ids, :product_distributions_attributes, :group_buy, :group_buy_unit_size
attr_accessible :variant_unit, :variant_unit_scale, :variant_unit_name, :unit_value, :unit_description, :notes, :images_attributes, :display_as
attr_accessible :supplier_id, :primary_taxon_id, :distributor_ids, :product_distributions_attributes
attr_accessible :group_buy, :group_buy_unit_size, :unit_description, :notes, :images_attributes, :display_as
attr_accessible :variant_unit, :variant_unit_scale, :variant_unit_name, :unit_value
attr_accessible :inherits_properties, :sku
validates_associated :master, message: "^Price and On Hand must be valid"
validates_presence_of :supplier
validates :primary_taxon, presence: { message: "^Product Category can't be blank" }
validates :tax_category_id, presence: { message: "^Tax Category can't be blank" }, if: "Spree::Config.products_require_tax_category"
validates_presence_of :variant_unit, if: :has_variants?
validates_presence_of :variant_unit_scale,
if: -> p { %w(weight volume).include? p.variant_unit }
@@ -106,19 +108,21 @@ Spree::Product.class_eval do
# -- Methods
def properties_h
def properties_including_inherited
# Product properties override producer properties
ps = supplier.producer_properties.inject(product_properties) do |properties, property|
if properties.find { |p| p.property.presentation == property.property.presentation }
properties
else
properties + [property]
ps = product_properties.all
if inherits_properties
supplier.producer_properties.each do |producer_property|
unless ps.find { |product_property| product_property.property.presentation == producer_property.property.presentation }
ps << producer_property
end
end
end
ps.
sort_by { |pp| pp.position }.
map { |pp| {presentation: pp.property.presentation, value: pp.value} }
map { |pp| {id: pp.property.id, name: pp.property.presentation, value: pp.value} }
end
def in_distributor?(distributor)

View File

@@ -3,7 +3,11 @@ module Spree
def ensure_correct_adjustment_with_included_tax
ensure_correct_adjustment_without_included_tax
adjustment.set_included_tax! Config.shipping_tax_rate if Config.shipment_inc_vat
if Config.shipment_inc_vat && (order.distributor.nil? || order.distributor.charges_sales_tax)
adjustment.set_included_tax! Config.shipping_tax_rate
else
adjustment.set_included_tax! 0
end
end
alias_method_chain :ensure_correct_adjustment, :included_tax

Some files were not shown because too many files have changed in this diff Show More