diff --git a/Gemfile b/Gemfile index f8407decdc..45b260c4c8 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,7 @@ gem 'jquery-rails' gem 'jquery-migrate-rails' gem 'css_splitter' +gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz' group :test, :development do # Pretty printed test output diff --git a/Gemfile.lock b/Gemfile.lock index 824f8a0c04..e03e350866 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,13 @@ GIT paypal-sdk-merchant (= 1.106.1) spree_core (~> 1.3.4) +GIT + remote: git://github.com/openfoodfoundation/ofn-qz.git + revision: 024680ccea429b2e5428d7b964fa67c52add34ec + specs: + ofn-qz (0.1.0) + railties (~> 3.1) + GIT remote: git://github.com/openfoodfoundation/spree.git revision: a4c439570b77afa50f9e36299811f293232bd281 @@ -694,6 +701,7 @@ DEPENDENCIES momentjs-rails newrelic_rpm nokogiri (>= 1.6.7.1) + ofn-qz! oj paper_trail (~> 3.0.8) paperclip @@ -737,4 +745,4 @@ RUBY VERSION ruby 2.1.5p273 BUNDLED WITH - 1.13.6 + 1.14.3 diff --git a/app/assets/javascripts/templates/admin/links_dropdown.html.haml b/app/assets/javascripts/templates/admin/links_dropdown.html.haml index 6d0ba060e2..13db5f7fb2 100644 --- a/app/assets/javascripts/templates/admin/links_dropdown.html.haml +++ b/app/assets/javascripts/templates/admin/links_dropdown.html.haml @@ -1,7 +1,7 @@ .ofn-drop-down %span %i.icon-check - Actions + = t('admin.actions') %i{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" } %div.menu{ 'ng-show' => "expanded" } %a.menu_item{ 'ng-repeat' => "link in links", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method || 'get' }}", confirm: "{{link.confirm}}" } } diff --git a/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml b/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml index 6a0d720a5f..e4f2eda259 100644 --- a/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml +++ b/app/assets/javascripts/templates/admin/modals/tag_rule_help.html.haml @@ -1,18 +1,19 @@ #tag-rule-help .margin-bottom-30.text-center - .text-big Tag Rules + .text-big + = t('js.admin.modals.tag_rule_help.title') .margin-bottom-30 - .text-normal Overview - %p Tag rules provide a way to describe which items are visible or otherwise to which customers. Items can be Shipping Methods, Payment Methods, Products and Order Cycles. + .text-normal= t('js.admin.modals.tag_rule_help.overview') + %p= t('js.admin.modals.tag_rule_help.overview_text') .margin-bottom-30 - .text-normal 'By Default...' Rules - %p Default rules allow you to hide items so that they are not visible by default. This behaviour can then be overriden by non-default rules for customers with particular tags. + .text-normal= t('js.admin.modals.tag_rule_help.by_default_rules') + %p= t('js.admin.modals.tag_rule_help.by_default_rules_text') .margin-bottom-30 - .text-normal 'Customers Tagged...' Rules - %p By creating rules related to a specific customer tag, you can override the default behaviour (whether it be to show or to hide items) for customers with the specified tag. + .text-normal= t('js.admin.modals.tag_rule_help.customer_tagged_rules') + %p= t('js.admin.modals.tag_rule_help.customer_tagged_rules_text') .text-center - %input.button.red.icon-plus{ type: 'button', value: 'Got it', ng: { click: 'close()' } } + %input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } } diff --git a/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml b/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml index 653e0d175d..fc746b1335 100644 --- a/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml +++ b/app/assets/javascripts/templates/admin/new_tag_rule_dialog.html.haml @@ -1,6 +1,6 @@ #new-tag-rule-dialog .text-normal.margin-bottom-30.text-center - Select a rule type: + = t('js.admin.new_tag_rule_dialog.select_rule_type') .text-center.margin-bottom-30 -# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' } diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml index 7f143d1071..27e1db7365 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_package.html.haml @@ -2,130 +2,128 @@ .alpha.eight.columns %div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } } .info{ ng: { switch: { when: "none" } } } - %h3 Hub Profile + %h3= t('js.admin.panels.enterprise_package.hub_profile') %p - %strong COST: ALWAYS FREE + %strong= t('js.admin.panels.enterprise_package.hub_profile_cost') - %p People can find and contact you on the Open Food Network. Your enterprise will be visible on the map, and will be searchable in listings. + %p= t('js.admin.panels.enterprise_package.hub_profile_text1') - %p Having a profile, and making connections within your local food system through the Open Food Network will always be free. + %p= t('js.admin.panels.enterprise_package.hub_profile_text2') .info{ ng: { switch: { when: "any" } } } - %h3 Hub Shop + %h3= t('js.admin.panels.enterprise_package.hub_shop') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Your enterprise is the backbone of your local food system. You aggregate produce from other enterprises and can sell it through your shop on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.hub_shop_text1') - %p Hubs can take many forms, whether they be a food co-op, a buying group, a veggie-box program, or a local grocery store. + %p= t('js.admin.panels.enterprise_package.hub_shop_text2') - %p If you also want to sell your own products, you will need to switch this enterprise to be a producer. + %p= t('js.admin.panels.enterprise_package.hub_shop_text3') .info{ ng: { switch: { default: true } } } %h3 - Please Choose a Package + = t('js.admin.panels.enterprise_package.choose_package') %i.icon-arrow-right %p - %strong Your enterprise will not be fully activated until a package is selected from the options on the left. + %strong= t('js.admin.panels.enterprise_package.choose_package_text1') %p - Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done! - - + = t('js.admin.panels.enterprise_package.choose_package_text2') %div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } } .info{ ng: { switch: { when: "none" } } } - %h3 Profile Only + %h3= t('js.admin.panels.enterprise_package.profile_only') %p - %strong COST: ALWAYS FREE + %strong= t('js.admin.panels.enterprise_package.profile_only_cost') - %p A profile makes you visible and contactable to others and is a way to share your story. + %p= t('js.admin.panels.enterprise_package.profile_only_text1') - %p If you prefer to focus on producing food, and want to leave the work of selling it to someone else, you won't require a shop on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.profile_only_text2') - %p Add your products to Open Food Network, allowing hubs to stock your products in their stores. + %p= t('js.admin.panels.enterprise_package.profile_only_text3') .info{ ng: { switch: { when: "own" } } } - %h3 Producer Shop + %h3= t('js.admin.panels.enterprise_package.producer_shop') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Sell your products directly to customers through your very own Open Food Network shopfront. + %p= t('js.admin.panels.enterprise_package.producer_shop_text1') - %p A Producer Shop is for your produce only, if you want to sell produce grown/produced off site, please select 'Producer Hub'. + %p= t('js.admin.panels.enterprise_package.producer_shop_text2') .info{ ng: { switch: { when: "any" } } } - %h3 Producer Hub + %h3= t('js.admin.panels.enterprise_package.producer_hub') %p %strong %monthly-pricing-description{ joiner: "comma" } - %p Your enterprise is the backbone of your local food system. You can sell your own produce as well as produce aggregated from other enterprises through your shopfront on the Open Food Network. + %p= t('js.admin.panels.enterprise_package.producer_hub_text1') - %p Producer Hubs can take many forms, whether they be a CSA, a veggie-box program, or a food co-op with a rooftop garden. + %p= t('js.admin.panels.enterprise_package.producer_hub_text2') - %p The Open Food Network aims to support as many hub models as possible, so no matter your situation, we want to provide the tools you need to run your organisation or local food business. + %p= t('js.admin.panels.enterprise_package.producer_hub_text3') .info{ ng: { switch: { default: true } } } %h3 - Please Choose a Package + = t('js.admin.panels.enterprise_package.choose_package') %i.icon-arrow-right %p - %strong Your producer enterprise will not be fully activated until a package is selected from the options on the left. + %strong= t('js.admin.panels.enterprise_package.choose_package_text1') %p - Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done! + = t('js.admin.panels.enterprise_package.choose_package_text2') .omega.eight.columns{ ng: { switch: "enterprise.is_primary_producer" } } %div{ ng: { switch: { when: "false" } } } %a.button.selector.hub-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } } .top - %h3 Profile Only - %p Get a listing - .bottom ALWAYS FREE + %h3= t('js.admin.panels.enterprise_package.profile_only') + %p= t('js.admin.panels.enterprise_package.get_listing') + .bottom= t('js.admin.panels.enterprise_package.always_free') %a.button.selector.hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } } .top - %h3 Hub Shop - %p Sell produce from others + %h3= t('js.admin.panels.enterprise_package.hub_shop') + %p= t('js.admin.panels.enterprise_package.sell_produce_others') .bottom %monthly-pricing-description{ joiner: "newline" } %div{ ng: { switch: { when: "true" } } } %a.button.selector.producer-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } } .top - %h3 Profile Only - %p Get a listing - .bottom ALWAYS FREE + %h3= t('js.admin.panels.enterprise_package.profile_only') + %p= t('js.admin.panels.enterprise_package.get_listing') + .bottom= t('js.admin.panels.enterprise_package.always_free') %a.button.selector.producer-shop{ ng: { click: "enterprise.owned && (enterprise.sells='own')", class: "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" } } .top - %h3 Producer Shop - %p Sell your own produce + %h3= t('js.admin.panels.enterprise_package.producer_shop') + %p= t('js.admin.panels.enterprise_package.sell_own_produce') .bottom %monthly-pricing-description{ joiner: "newline" } %a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } } .top - %h3 Producer Hub - %p Sell produce from self and others + %h3= t('js.admin.panels.enterprise_package.producer_hub') + %p= t('js.admin.panels.enterprise_package.sell_both') .bottom %monthly-pricing-description{ joiner: "newline" } %a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } } %span{ ng: {hide: "saved() || saving" } } - SAVE + = t('js.admin.panels.save') %i.icon-save %span{ ng: {show: "saved() && !saving" } } - SAVED + = t('js.admin.panels.saved') %i.icon-ok-sign %span{ ng: {show: "saving" } } - SAVING + = t('js.admin.panels.saving') %i.icon-refresh diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml index ea8554892f..b30b15aa63 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_producer.html.haml @@ -1,39 +1,37 @@ .row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } } - .alpha.eight.columns .info{ ng: { show: "enterprise.is_primary_producer==true" } } - %h3 Producer - %p Producers make yummy things to eat &/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it. - - %p Producers can also perform other functions, such as aggregating food from other enterprises and selling it through a shop on the Open Food Network. + %h3= t('js.admin.panels.enterprise_producer.producer') + %p= t('js.admin.panels.enterprise_producer.producer_text1') + %p= t('js.admin.panels.enterprise_producer.producer_text2') .info{ ng: { show: "enterprise.is_primary_producer==false" } } - %h3 Non-Producer - %p Non-producers do not produce any food themselves, meaning that they cannot create their own products for sale through the Open Food Network. + %h3= t('js.admin.panels.enterprise_producer.non_producer') + %p= t('js.admin.panels.enterprise_producer.non_producer_text1') - %p Instead, non-producers specialise in linking producers to the end eater, whether it be by aggregating, grading, packing, selling or delivering food. + %p= t('js.admin.panels.enterprise_producer.non_producer_text2') .omega.eight.columns %a.button.selector.producer{ ng: { click: 'enterprise.owned && changeToProducer()', class: "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" } } .top - %h3 PRODUCER - %p Producers of food - .bottom eg. GROWERS, BAKERS, BREWERS, MAKERS + %h3= t('js.admin.panels.enterprise_producer.producer') + %p= t('js.admin.panels.enterprise_producer.producer_desc') + .bottom= t('js.admin.panels.enterprise_producer.producer_example') %a.button.selector.non-producer{ ng: { click: 'enterprise.owned && changeToNonProducer()', class: "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" } } .top - %h3 Non-Producer - %p All other food enterprises - .bottom eg. Grocery stores, Food co-ops, Buying groups + %h3= t('js.admin.panels.enterprise_producer.non_producer') + %p= t('js.admin.panels.enterprise_producer.non_producer_desc') + .bottom= t('js.admin.panels.enterprise_producer.non_producer_example') %a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } } %span{ ng: {hide: "saved() || saving" } } - SAVE + = t('js.admin.panels.save') %i.icon-save %span{ ng: {show: "saved() && !saving" } } - SAVED + = t('js.admin.panels.saved') %i.icon-ok-sign %span{ ng: {show: "saving" } } - SAVING + = t('js.admin.panels.saving') %i.icon-refresh diff --git a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml index 518122774d..305210b3ee 100644 --- a/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml +++ b/app/assets/javascripts/templates/admin/panels/enterprise_status.html.haml @@ -1,18 +1,17 @@ .row.enterprise_status_panel{ ng: { controller: 'indexStatusPanelCtrl' } } .alpha.omega.sixteen.columns - %h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } } %i.icon-ok-sign - {{ object.name }} is set up and ready to go! + = t('js.admin.panels.enterprise_status.status_title', name: '{{ object.name }}') %table{ ng: { show: "issues.length > 0 || warnings.length > 0" } } %thead %th.severity - Severity + = t('js.admin.panels.enterprise_status.severity') %th.description - Description + = t('js.admin.panels.enterprise_status.description') %th.resolve - Resolve + = t('js.admin.panels.enterprise_status.resolve') %tr{ ng: { repeat: "issue in issues"} } %td.severity %i.icon-warning-sign.issue diff --git a/app/assets/javascripts/templates/admin/show_more.html.haml b/app/assets/javascripts/templates/admin/show_more.html.haml index f9a008993c..0800710927 100644 --- a/app/assets/javascripts/templates/admin/show_more.html.haml +++ b/app/assets/javascripts/templates/admin/show_more.html.haml @@ -1,4 +1,4 @@ %div{ ng: { show: "data.length > limit" } } - %input{ type: 'button', value: 'Show More', ng: { click: 'limit = limit + increment' } } + %input{ type: 'button', value: t(:show_more), ng: { click: 'limit = limit + increment' } } or - %input{ type: 'button', value: "Show All ({{ data.length - limit }} More)", ng: { click: 'limit = data.length' } } + %input{ type: 'button', value: t(:show_more_with_more, num: '{{ data.length - limit }}'), ng: { click: 'limit = data.length' } } diff --git a/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml b/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml index 49ff00ff27..9a6d4e9c26 100644 --- a/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml +++ b/app/assets/javascripts/templates/admin/tag_autocomplete.html.haml @@ -3,9 +3,9 @@ {{$getDisplayText()}} %span.tag-with-rules{ ng: { if: "data.rules == 1" } } — - = t 'admin.has_one_rule' + = t('admin.has_one_rule') %span.tag-with-rules{ ng: { if: "data.rules > 1" } } — - = t 'admin.has_n_rules', { num: '{{data.rules}}' } + = t('admin.has_n_rules', { num: '{{data.rules}}' }) %span{ ng: { if: "!data.rules" } } {{$getDisplayText()}} diff --git a/app/assets/javascripts/templates/out_of_stock.html.haml b/app/assets/javascripts/templates/out_of_stock.html.haml index d894583fcf..5a9662fb6b 100644 --- a/app/assets/javascripts/templates/out_of_stock.html.haml +++ b/app/assets/javascripts/templates/out_of_stock.html.haml @@ -1,13 +1,13 @@ %a.close-reveal-modal{"ng-click" => "$close()"} %i.ofn-i_009-close -%h3 Reduced stock available +%h3= t('js.out_of_stock.reduced_stock_available') -%p While you've been shopping, the stock levels for one or more of the products in your cart have reduced. Here's what's changed: +%p= t('js.out_of_stock.out_of_stock_text') %p{'ng-repeat' => "v in variants"} %em {{ v.name_to_display }} - {{ v.unit_to_display }} %span{'ng-if' => "v.count_on_hand == 0"} - is now out of stock. + = t('js.out_of_stock.now_out_of_stock') %span{'ng-if' => "v.count_on_hand > 0"} - now only has {{ v.count_on_hand }} remaining. + = t('js.out_of_stock.only_n_remainging', num: '{{ v.count_on_hand }}') diff --git a/app/assets/javascripts/templates/registration.html.haml b/app/assets/javascripts/templates/registration.html.haml deleted file mode 100644 index 10a12d712e..0000000000 --- a/app/assets/javascripts/templates/registration.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -%div#registration-modal{"ng-controller" => "RegistrationCtrl"} - %div{ ng: { show: "currentStep() == 'introduction'" } } - %ng-include{ src: "'registration/introduction.html'" } - %div{ ng: { repeat: 'step in steps', show: "currentStep() == step" } } - %ng-include{ src: "'registration/'+ step + '.html'" } - %div{ ng: { show: "currentStep() == 'finished'" } } - %ng-include{ src: "'registration/finished.html'" } - -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/registration/about.html.haml b/app/assets/javascripts/templates/registration/about.html.haml deleted file mode 100644 index 40d02e3d32..0000000000 --- a/app/assets/javascripts/templates/registration/about.html.haml +++ /dev/null @@ -1,57 +0,0 @@ -.container#registration-about - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'enterprise_about_headline' | t}} - %h5 - {{'enterprise_about_message' | t}} - %span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } } - {{ enterprise.name }} - - %form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('images',about)" } } - .row - .small-12.columns - .alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } } - %h6{ "ng-bind" => "'enterprise_success' | t:{enterprise: enterprise.name}" } - %span {{'enterprise_registration_exit_message' | t}} - %a.close{ ng: { click: "close()" } } × - - .small-12.large-8.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_description' } {{'enterprise_description' | t}}: - %input.chunky{ id: 'enterprise_description', placeholder: "{{'enterprise_description_placeholder' | t}}", ng: { model: 'enterprise.description' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_long_desc' } {{'enterprise_long_desc' | t}}: - %textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "{{'enterprise_long_desc_placeholder' | t}}", ng: { model: 'enterprise.long_description' } } - %small{ "ng-bind" => "'enterprise_long_desc_length' | t:{num: enterprise.long_description.length}" } - .small-12.large-4.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_abn' } {{'enterprise_abn' | t}}: - %input.chunky{ id: 'enterprise_abn', placeholder: "{{'enterprise_abn_placeholder' | t}}", ng: { model: 'enterprise.abn' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_acn' } {{'enterprise_acn' | t}}: - %input.chunky{ id: 'enterprise_acn', placeholder: "{{'enterprise_acn_placeholder' | t}}", 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' } {{'say_yes' | t}} - %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' } {{'say_no' | t}} - %span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } } - {{'enterprise_tax_required' | t}} - - .row.buttons.pad-top - .small-12.columns - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } - diff --git a/app/assets/javascripts/templates/registration/contact.html.haml b/app/assets/javascripts/templates/registration/contact.html.haml deleted file mode 100644 index a22b0677a7..0000000000 --- a/app/assets/javascripts/templates/registration/contact.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -.container#registration-contact - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_greeting' | t}} - %h5{ "ng-bind" => "'who_is_managing_enterprise' | t:{enterprise: enterprise.name}" } - - %form{ name: 'contact', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('type',contact)" } } - .row.content - .small-12.medium-12.large-7.columns - .row - .small-12.columns.field - %label{ for: 'enterprise_contact' } {{'enterprise_contact' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_contact', name: 'contact', required: true, placeholder: "Contact Name", ng: { model: 'enterprise.contact' } } - %span.error.small-12.columns{ ng: { show: "contact.contact.$error.required && submitted" } } - {{'enterprise_contact_required' | t}} - .row - .small-12.columns.field - %label{ for: 'enterprise_email_address' } {{'enterprise_email_address' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_email_address', name: 'email_address', type: 'email', placeholder: "eg. charlie@thefarm.com", ng: { model: 'enterprise.email_address' } } - .row - .small-12.columns.field - %label{ for: 'enterprise_phone' } {{'enterprise_phone' | t}}: - %input.chunky.small-12.columns{ id: 'enterprise_phone', name: 'phone', placeholder: "eg. (03) 1234 5678", ng: { model: 'enterprise.phone' } } - .small-12.medium-12.large-5.hide-for-small-only - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('details')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/details.html.haml b/app/assets/javascripts/templates/registration/details.html.haml deleted file mode 100644 index 6bd3fc02ba..0000000000 --- a/app/assets/javascripts/templates/registration/details.html.haml +++ /dev/null @@ -1,64 +0,0 @@ -.container#registration-details - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_detail_headline' | t}} - %h5{ ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}} - %h5{ ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_producer' | t}} - - %form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } } - - .row - .small-12.medium-9.large-12.columns.end - .field - %label{ for: 'enterprise_name', ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}} - %label{ for: 'enterprise_name', ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}} - %input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } } - %span.error{ ng: { show: "details.name.$error.required && submitted" } } - {{'registration_detail_name_error' | t}} - - .row - .small-12.medium-9.large-6.columns - .field - %label{ for: 'enterprise_address' } {{'registration_detail_address1' | t}} - %input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "{{'registration_detail_address1_placeholder' | t}}", required: true, ng: { model: 'enterprise.address.address1' } } - %span.error{ ng: { show: "details.address1.$error.required && submitted" } } - {{'registration_detail_address1_error' | t}} - .field - %label{ for: 'enterprise_address2' } {{'registration_detail_address2' | t}} - %input.chunky{ id: 'enterprise_address2', name: 'address2', required: false, placeholder: "", required: false, ng: { model: 'enterprise.address.address2' } } - - .small-12.medium-9.large-6.columns.end - .row - .small-12.medium-8.large-8.columns - .field - %label{ for: 'enterprise_city' } {{'registration_detail_suburb' | t}} - %input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "{{'registration_detail_suburb_placeholder' | t}}", ng: { model: 'enterprise.address.city' } } - %span.error{ ng: { show: "details.city.$error.required && submitted" } } - {{'registration_detail_suburb_error' | t}} - .small-12.medium-4.large-4.columns - .field - %label{ for: 'enterprise_zipcode' } {{'registration_detail_postcode' | t}} - %input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "{{'registration_detail_postcode_placeholder' | t}}", ng: { model: 'enterprise.address.zipcode' } } - %span.error{ ng: { show: "details.zipcode.$error.required && submitted" } } - {{'registration_detail_postcode_error' | t}} - .row - .small-12.medium-4.large-4.columns - .field - %label{ for: 'enterprise_state' } {{'registration_detail_state' | t}} - %select.chunky{ id: 'enterprise_state', name: 'state', ng: { model: 'enterprise.address.state_id', options: 's.id as s.abbr for s in enterprise.country.states', show: 'countryHasStates()', required: 'countryHasStates()' } } - %span.error{ ng: { show: "details.state.$error.required && submitted" } } - {{'registration_detail_state_error' | t}} - .small-12.medium-8.large-8.columns - .field - %label{ for: 'enterprise_country' } {{'registration_detail_country' | t}} - %select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { model: 'enterprise.country', options: 'c as c.name for c in countries' } } - %span.error{ ng: { show: "details.country.$error.required && submitted" } } - {{'registration_detail_country_error' | t}} - - - .row.buttons - .small-12.columns - %hr - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/finished.html.haml b/app/assets/javascripts/templates/registration/finished.html.haml deleted file mode 100644 index 76403cb1c8..0000000000 --- a/app/assets/javascripts/templates/registration/finished.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -.container#registration-finished - .row - .small-12.columns.pad-top - %header - %h2 {{'registration_finished_headline' | t}} - .panel.callout - %p{ "ng-bind" => "'registration_finished_thanks' | t:{enterprise: enterprise.name}" } - %p {{'registration_finished_login' | t}} - .row - .small-12.columns.text-center - %h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" } - - %p{ "ng-bind-html" => "'registration_finished_activate_instruction_html' | t:{email: enterprise.email}"} - - %a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} > diff --git a/app/assets/javascripts/templates/registration/images.html.haml b/app/assets/javascripts/templates/registration/images.html.haml deleted file mode 100644 index 60a1ca602b..0000000000 --- a/app/assets/javascripts/templates/registration/images.html.haml +++ /dev/null @@ -1,22 +0,0 @@ -.container#registration-images{ 'nv-file-drop' => true, uploader: "imageUploader", options:"{ alias: imageStep }", ng: { controller: "EnterpriseImageCtrl" } } - %ng-include{ src: "'registration/steps.html'" } - .row - .small-12.columns - %header - %h2 {{'registration_images_headline' | t}} - %h5 {{'registration_images_description' | t}} - - %form{ name: 'images', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "select('social')" } } - .row{ ng: { repeat: 'image_step in imageSteps', show: "imageStep == image_step" } } - %ng-include{ src: "'registration/images/'+ image_step + '.html'" } - - .row.buttons.pad-top{ ng: { if: "imageStep == 'logo'" } } - .small-12.columns - %input.button.secondary{ type: "button", value: "Back", ng: { click: "select('about')" } } -   - %input.button.primary.right{ type: "button", value: "Continue", ng: { click: "imageSelect('promo')" } } - - .row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } } - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "imageSelect('logo')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/assets/javascripts/templates/registration/images/logo.html.haml b/app/assets/javascripts/templates/registration/images/logo.html.haml deleted file mode 100644 index 842cbcbe11..0000000000 --- a/app/assets/javascripts/templates/registration/images/logo.html.haml +++ /dev/null @@ -1,45 +0,0 @@ -.small-12.medium-12.large-6.columns - .row - .small-12.columns.center - .row - .small-12.columns.center - %h4 - {{'select_logo' | t}} - .row - .small-12.columns.center - %span.small - {{'logo_tip' | t}} - .row.pad-top - .small-12.columns - .image-select.small-12.columns - %label.small-12.columns.button{ for: 'image-select' } {{'logo_label' | t}} - %input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' } - .row.show-for-large-up - .large-12.columns - %span#or.large-12.columns - {{'action_or' | t}} - .row.show-for-large-up - .large-12.columns - #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } - {{'logo_drag' | t}} -.small-12.medium-12.large-6.columns - .row - .small-12.columns.center - .row - .small-12.columns.center - %h4 - {{'review_logo' | t}} - .row - .small-12.columns.center - %span.small - {{'review_logo_tip' | t}} - .row.pad-top - .small-12.columns.center - #image-placeholder.logo - %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } - .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } - {{'logo_placeholder' | t}} - .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } - %br/ - {{'uploading' | t}} diff --git a/app/assets/javascripts/templates/registration/images/promo.html.haml b/app/assets/javascripts/templates/registration/images/promo.html.haml deleted file mode 100644 index 342db5c08d..0000000000 --- a/app/assets/javascripts/templates/registration/images/promo.html.haml +++ /dev/null @@ -1,43 +0,0 @@ -.small-12.medium-12.large-12.columns - .row - .small-12.columns.center - %h4 - {{'select_promo_image' | t}} - .row - .small-12.medium-12.large-5.columns.center - .row - .small-12.columns.center - %span.small - {{'promo_image_tip' | t}} - .row.pad-top - .small-12.columns - .image-select.small-12.columns - %label.small-12.columns.button{ for: 'image-select' } {{'promo_image_label' | t}} - %input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' } - .large-2.columns - %span#or.horizontal.large-12.columns - {{'action_or' | t}} - .large-5.columns - #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } - {{'promo_image_drag' | t}} -.small-12.medium-12.large-12.columns.pad-top - .row - .small-12.columns.center - %h4 - {{'review_promo_image' | t}} - .row - .small-12.columns.center - .row - .small-12.columns.center - %span.small - {{'review_promo_image_tip' | t}} - .row.pad-top - .small-12.columns.center - #image-placeholder.promo - %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } - .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } - {{'promo_image_placeholder' | t}} - .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } - %br/ - {{'uploading' | t}} diff --git a/app/assets/javascripts/templates/registration/introduction.html.haml b/app/assets/javascripts/templates/registration/introduction.html.haml deleted file mode 100644 index c0adb0c357..0000000000 --- a/app/assets/javascripts/templates/registration/introduction.html.haml +++ /dev/null @@ -1,41 +0,0 @@ -.row - .small-12.columns - %header - %h2 {{'registration_greeting' | t}} - %h4 - %small - %i.ofn-i_040-hub - {{'registration_intro' | t}} - .hide-for-large-up - %hr - %input.button.small.primary{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')" } } - %hr - -.row{ 'data-equalizer' => true } - .small-12.medium-12.large-6.columns.pad-top{ 'data-equalizer-watch' => true } - %h5 {{'registration_checklist' | t}}: - %ul.check-list - %li - {{'registration_time' | t}} - %li - {{'registration_enterprise_address' | t}} - %li - {{'registration_contact_details' | t}} - %li - {{'registration_logo' | t}} - %li - {{'registration_promo_image' | t}} - %li - {{'registration_about_us' | t}} - - .small-9.medium-8.large-5.columns.pad-top.end{ 'data-equalizer-watch' => true} - %h5 - {{'registration_outcome_headline' | t}} - %p{ "ng-bind-html" => "t('registration_outcome1_html')" } - %p {{'registration_outcome2' | t}} - %p {{'registration_outcome3' | t}} - -.row.show-for-large-up - .small-12.columns - %hr - %input.button.primary.right{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')" } } diff --git a/app/assets/javascripts/templates/registration/limit_reached.html.haml b/app/assets/javascripts/templates/registration/limit_reached.html.haml deleted file mode 100644 index 09e9866fd9..0000000000 --- a/app/assets/javascripts/templates/registration/limit_reached.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -.row - .small-12.columns - %header - %h2 {{'limit_reached_headline' | t}} - %h4 {{'limit_reached_message' | t}} -.row - .small-12.medium-3.large-2.columns.text-right.hide-for-small-only - %img{:src => "/assets/potatoes.png"} - .small-12.medium-9.large-10.columns - %p - {{'limit_reached_text' | t}} - %strong Open Food Network. -.row - .small-12.columns - %hr - %input.button.primary{ type: "button", value: "{{'limit_reached_action' | t}}", ng: { click: "close()" } } diff --git a/app/assets/javascripts/templates/registration/social.html.haml b/app/assets/javascripts/templates/registration/social.html.haml deleted file mode 100644 index ac40ef9c56..0000000000 --- a/app/assets/javascripts/templates/registration/social.html.haml +++ /dev/null @@ -1,45 +0,0 @@ -.container#registration-social - %ng-include{ src: "'registration/steps.html'" } - - .row - .small-12.columns - %header - %h2 {{'enterprise_final_step' | t}} - %h5{ "ng-bind" => "'enterprise_social_text' | t:{enterprise: enterprise.name}" } - - %form{ name: 'social', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('finished',social)" } } - .row.content - .small-12.large-7.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_website' } {{'website' | t}}: - %input.chunky{ id: 'enterprise_website', placeholder: "{{'website_placeholder' | t}}", ng: { model: 'enterprise.website' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_facebook' } {{'facebook' | t}}: - %input.chunky{ id: 'enterprise_facebook', placeholder: "{{'facebook_placeholder' | t}}", ng: { model: 'enterprise.facebook' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_linkedin' } {{'linkedin' | t}}: - %input.chunky{ id: 'enterprise_linkedin', placeholder: "{{'linkedin_placeholder' | t}}", ng: { model: 'enterprise.linkedin' } } - .small-12.large-5.columns - .row - .small-12.columns - .field - %label{ for: 'enterprise_twitter' } {{'twitter' | t}}: - %input.chunky{ id: 'enterprise_twitter', placeholder: "{{'twitter_placeholder' | t}}", ng: { model: 'enterprise.twitter' } } - .row - .small-12.columns - .field - %label{ for: 'enterprise_instagram' } {{'instagram' | t}}: - %input.chunky{ id: 'enterprise_instagram', placeholder: "{{'instagram_placeholder' | t}}", ng: { model: 'enterprise.instagram' } } - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('images')" } } - %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } - - diff --git a/app/assets/javascripts/templates/registration/steps.html.haml b/app/assets/javascripts/templates/registration/steps.html.haml deleted file mode 100644 index 8b420de293..0000000000 --- a/app/assets/javascripts/templates/registration/steps.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -.row#progress-bar - .small-12.medium-2.columns.item{ ng: { repeat: 'step in steps', class: "{active: (currentStep() == step),'show-for-medium-up': (currentStep() != step)}" } } - {{ $index+1 + ". " + step }} diff --git a/app/assets/javascripts/templates/registration/type.html.haml b/app/assets/javascripts/templates/registration/type.html.haml deleted file mode 100644 index 85a81398d7..0000000000 --- a/app/assets/javascripts/templates/registration/type.html.haml +++ /dev/null @@ -1,47 +0,0 @@ -.container#registration-type - - %ng-include{ src: "'registration/steps.html'" } - - .row - .small-12.columns - %header - %h2{ "ng-bind" => "'registration_type_headline' | t:{enterprise: enterprise.name}" } - %h4 - {{'registration_type_question' | t}} - - %form{ name: 'type', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "create(type)" } } - .row#enterprise-types{ 'data-equalizer' => true, ng: { if: "::enterprise.type != 'own'" } } - .small-12.columns.field - .row - .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } - %a.btnpanel#producer-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = true", class: "{selected: enterprise.is_primary_producer}" } } - %i.ofn-i_059-producer - %h4 {{'registration_type_producer' | t}} - - .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } - %a.btnpanel#hub-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = false", class: "{selected: enterprise.is_primary_producer == false}" } } - %i.ofn-i_063-hub - %h4 {{'registration_type_no_producer' | t}} - - .row - .small-12.columns - %input.chunky{ id: 'enterprise_is_primary_producer', name: 'is_primary_producer', hidden: true, required: true, ng: { model: 'enterprise.is_primary_producer' } } - %span.error{ ng: { show: "type.is_primary_producer.$error.required && submitted" } } - {{'registration_type_error' | t}} - .row - .small-12.columns - .panel.callout - .left - %i.ofn-i_013-help -   - %p {{'registration_type_producer_help' | t}} - .panel.callout - .left - %i.ofn-i_013-help -   - %p {{'registration_type_no_producer_help' | t}} - - .row.buttons - .small-12.columns - %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('contact')" } } - %input.button.primary.right{ type: "submit", value: "{{'create_profile' | t}}" } diff --git a/app/controllers/admin/business_model_configuration_controller.rb b/app/controllers/admin/business_model_configuration_controller.rb index b3c3c67ab8..1cf2ad088d 100644 --- a/app/controllers/admin/business_model_configuration_controller.rb +++ b/app/controllers/admin/business_model_configuration_controller.rb @@ -6,7 +6,8 @@ class Admin::BusinessModelConfigurationController < Spree::Admin::BaseController def update Spree::Config.set(params[:settings]) - flash[:success] = t(:successfully_updated, :resource => t(:business_model_configuration)) + flash[:success] = t(:successfully_updated, + resource: t('admin.business_model_configuration.edit.business_model_configuration')) redirect_to_edit end diff --git a/app/controllers/admin/invoice_settings_controller.rb b/app/controllers/admin/invoice_settings_controller.rb new file mode 100644 index 0000000000..ac65c9860e --- /dev/null +++ b/app/controllers/admin/invoice_settings_controller.rb @@ -0,0 +1,13 @@ +class Admin::InvoiceSettingsController < Spree::Admin::BaseController + + def update + Spree::Config.set(params[:preferences]) + + respond_to do |format| + format.html { + redirect_to main_app.edit_admin_invoice_settings_path + } + end + end + +end diff --git a/app/controllers/spree/admin/orders_controller_decorator.rb b/app/controllers/spree/admin/orders_controller_decorator.rb index b5a2bb4f95..129d4c3308 100644 --- a/app/controllers/spree/admin/orders_controller_decorator.rb +++ b/app/controllers/spree/admin/orders_controller_decorator.rb @@ -77,7 +77,8 @@ Spree::Admin::OrdersController.class_eval do end def invoice - pdf = render_to_string pdf: "invoice-#{@order.number}.pdf", template: "spree/admin/orders/invoice", formats: [:html], encoding: "UTF-8" + template = if Spree::Config.invoice_style2? then "spree/admin/orders/invoice2" else "spree/admin/orders/invoice" end + pdf = render_to_string pdf: "invoice-#{@order.number}.pdf", template: template, formats: [:html], encoding: "UTF-8" Spree::OrderMailer.invoice_email(@order.id, pdf).deliver flash[:success] = t(:invoice_email_sent) @@ -85,7 +86,12 @@ Spree::Admin::OrdersController.class_eval do end def print - render pdf: "invoice-#{@order.number}", template: "spree/admin/orders/invoice", encoding: "UTF-8" + template = if Spree::Config.invoice_style2? then "spree/admin/orders/invoice2" else "spree/admin/orders/invoice" end + render pdf: "invoice-#{@order.number}", template: template, encoding: "UTF-8" + end + + def print_ticket + render template: "spree/admin/orders/ticket", layout: false end def update_distribution_charge diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 8441b2d596..8a5a5fa2b2 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -38,6 +38,10 @@ Spree::Admin::ReportsController.class_eval do ["Payment Methods Report", :payment_methods], ["Delivery Report", :delivery] ], + sales_tax: [ + ["Tax Types", :tax_types], + ["Tax Rates", :tax_rates] + ], packing: [ ["Pack By Customer", :pack_by_customer], ["Pack By Supplier", :pack_by_supplier] @@ -59,6 +63,8 @@ Spree::Admin::ReportsController.class_eval do render_to_string(partial: 'order_cycle_management_description', layout: false, locals: {report_types: REPORT_TYPES[:order_cycle_management]}).html_safe @reports[:packing][:description] = render_to_string(partial: 'packing_description', layout: false, locals: {report_types: REPORT_TYPES[:packing]}).html_safe + @reports[:sales_tax][:description] = + render_to_string(partial: 'sales_tax_description', layout: false, locals: {report_types: REPORT_TYPES[:sales_tax]}).html_safe } } } @@ -159,6 +165,7 @@ Spree::Admin::ReportsController.class_eval do def sales_tax prepare_date_params params @distributors = Enterprise.is_distributor.managed_by(spree_current_user) + @report_type = params[:report_type] @report = OpenFoodNetwork::SalesTaxReport.new spree_current_user, params @@ -320,8 +327,7 @@ Spree::Admin::ReportsController.class_eval do :order_cycle_management => {:name => "Order Cycle Management", :description => ''}, :sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" }, :xero_invoices => { :name => "Xero Invoices", :description => 'Invoices for import into Xero' }, - :packing => { :name => "Packing Reports", :description => '' }, - :sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" } + :packing => { :name => "Packing Reports", :description => '' } } # Return only reports the user is authorized to view. reports.select { |action| can? action, :report } diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb index 57cbfd7b73..f55a619f2b 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -43,6 +43,29 @@ module CheckoutHelper Spree::Money.new order.total_tax, currency: order.currency end + def display_checkout_taxes_hash(order) + order.tax_adjustment_totals.each_with_object(Hash.new) do |(tax_rate, tax_amount), hash| + hash[number_to_percentage(tax_rate * 100, :precision => 1)] = Spree::Money.new tax_amount, currency: order.currency + end + end + + def display_line_item_tax_rates(line_item) + line_item.tax_rates.map { |tr| number_to_percentage(tr.amount * 100, :precision => 1) }.join(", ") + end + + def display_adjustment_tax_rates(adjustment) + tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) + if tax_rate == 0 || tax_rate.infinite? + "" + else + number_to_percentage(tax_rate * 100, :precision => 1) + end + end + + def display_adjustment_amount(adjustment) + Spree::Money.new(adjustment.amount, { :currency => adjustment.currency }) + end + def display_checkout_total_less_tax(order) Spree::Money.new order.total - order.total_tax, currency: order.currency end diff --git a/app/helpers/spree/admin/orders_helper_decorator.rb b/app/helpers/spree/admin/orders_helper_decorator.rb index 23443cc400..94a850bb7f 100644 --- a/app/helpers/spree/admin/orders_helper_decorator.rb +++ b/app/helpers/spree/admin/orders_helper_decorator.rb @@ -13,6 +13,10 @@ module Spree links << { name: t(:send_invoice), url: "#", icon: 'icon-email', confirm: t(:must_have_valid_business_number, enterprise_name: order.distributor.name) } end links << { name: t(:print_invoice), url: print_admin_order_path(order), icon: 'icon-print', target: "_blank" } + if Spree::Config.enable_receipt_printing? + links << { name: t(:print_ticket), url: print_ticket_admin_order_path(order), icon: 'icon-print', target: "_blank" } + links << { name: t(:select_ticket_printer), url: "#{print_ticket_admin_order_path(order)}#select-printer", icon: 'icon-print', target: "_blank" } + end end if @order.ready_to_ship? links << { name: t(:ship_order), url: fire_admin_order_path(@order, :e => 'ship'), method: 'put', icon: 'icon-truck', confirm: t(:are_you_sure) } diff --git a/app/models/spree/address_decorator.rb b/app/models/spree/address_decorator.rb index 03fa4da0cd..db092f5eb2 100644 --- a/app/models/spree/address_decorator.rb +++ b/app/models/spree/address_decorator.rb @@ -20,6 +20,18 @@ Spree::Address.class_eval do filtered_address.compact.join(', ') end + def address_part1 + address_part1 = [address1, address2] + filtered_address = address_part1.select{ |field| !field.nil? && field != '' } + filtered_address.compact.join(', ') + end + + def address_part2 + address_part2= [city, zipcode, state.andand.name] + filtered_address = address_part2.select{ |field| !field.nil? && field != '' } + filtered_address.compact.join(', ') + end + private def touch_enterprise diff --git a/app/models/spree/adjustment_decorator.rb b/app/models/spree/adjustment_decorator.rb index c8529fc577..093f1c86fd 100644 --- a/app/models/spree/adjustment_decorator.rb +++ b/app/models/spree/adjustment_decorator.rb @@ -4,6 +4,7 @@ module Spree # So we don't need the option `dependent: :destroy` as long as # AdjustmentMetadata has no destroy logic itself. has_one :metadata, class_name: 'AdjustmentMetadata' + belongs_to :tax_rate, foreign_key: 'originator_id', conditions: "spree_adjustments.originator_type = 'Spree::TaxRate'" scope :enterprise_fee, where(originator_type: 'EnterpriseFee') scope :billable_period, where(source_type: 'BillablePeriod') diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 570c7acc1e..2dfda8949c 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -4,6 +4,10 @@ Spree::AppConfiguration.class_eval do # we can allow to be modified in the UI by adding appropriate form # elements to existing or new configuration pages. + # Terms of Service Preferences + preference :enterprises_require_tos, :boolean, default: false + preference :enterprise_tos_link, :string, default: "/Terms-of-service.pdf" + # Tax Preferences preference :products_require_tax_category, :boolean, default: false preference :shipping_tax_rate, :decimal, default: 0 @@ -28,4 +32,8 @@ Spree::AppConfiguration.class_eval do # External services preference :bugherd_api_key, :string, default: nil + + # Invoices & Receipts + preference :invoice_style2?, :boolean, default: false + preference :enable_receipt_printing?, :boolean, default: false end diff --git a/app/models/spree/line_item_decorator.rb b/app/models/spree/line_item_decorator.rb index 8a89d8fdef..31d263761f 100644 --- a/app/models/spree/line_item_decorator.rb +++ b/app/models/spree/line_item_decorator.rb @@ -56,6 +56,10 @@ Spree::LineItem.class_eval do adjustments.included_tax.sum(&:included_tax) end + def tax_rates + product.tax_category.andand.tax_rates || [] + end + 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 diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index c62f114177..8212840a8d 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -227,6 +227,26 @@ Spree::Order.class_eval do (adjustments + price_adjustments).sum &:included_tax end + def tax_adjustments + adjustments.with_tax + + line_items.includes(:adjustments).map {|li| li.adjustments.with_tax }.flatten + end + + def tax_adjustment_totals + tax_adjustments.each_with_object(Hash.new) do |adjustment, hash| + if adjustment.originator_type == "Spree::TaxRate" + tax_rate = adjustment.originator.amount + else + tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) + end + hash.update({tax_rate => adjustment.included_tax}) { |_tax_rate, amount1, amount2| amount1 + amount2 } + end + end + + def has_taxes_included + not line_items.with_tax.empty? + end + def account_invoice? distributor_id == Spree::Config.accounts_distributor_id end diff --git a/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface b/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface new file mode 100644 index 0000000000..9d573c3ac1 --- /dev/null +++ b/app/overrides/spree/admin/general_settings/edit/tos_settings.html.haml.deface @@ -0,0 +1,11 @@ +/ insert_after "fieldset.security" + +%fieldset.enterprise_toc.no-border-bottom + %legend{:align => "center"}= t(:enterprise_terms_of_service) + - [:enterprise_tos_link, :enterprises_require_tos].each do |pref| + - type = Spree::Config.preference_type(pref) + .field + = label_tag(pref, t(pref) + ': ') + tag(:br) if type != :boolean + = preference_field_tag(pref, Spree::Config[pref], :type => type) + = label_tag(pref, t(pref)) + tag(:br) if type == :boolean + diff --git a/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface index d5be7e956c..bba71ef434 100644 --- a/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/orders/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_top "[data-hook='admin_orders_index_headers']" %th - Distributor + = t(:products_distributor) diff --git a/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface index b14ca58392..6a46fe448c 100644 --- a/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/payment_methods/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='admin_payment_methods_index_headers'] th:first-child" %th - Distributors + = t(:products_distributor) diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface index 37754bb40e..eb6ab7c01b 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_accounts_and_billing.html.haml.deface @@ -1,4 +1,4 @@ // insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to t(:accounts_and_billing), main_app.edit_admin_accounts_and_billing_settings_path + = link_to t('admin.accounts_and_billing_settings.edit.accounts_and_billing'), main_app.edit_admin_accounts_and_billing_settings_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface index 7d5c311a7b..32d0edfda1 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_business_model_configuration.html.haml.deface @@ -1,4 +1,4 @@ // insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to 'Business Model', main_app.edit_admin_business_model_configuration_path + = link_to t('admin.business_model_configuration.edit.business_model_configuration'), main_app.edit_admin_business_model_configuration_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface index 1eb416e72a..c320e072c0 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_caching.html.haml.deface @@ -1,4 +1,4 @@ / insert_bottom "[data-hook='admin_configurations_sidebar_menu']" %li - = link_to 'Caching', main_app.admin_cache_settings_path + = link_to t('admin.cache_settings.show.title'), main_app.admin_cache_settings_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface index 0709cb9451..58ba1fc824 100644 --- a/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_content.html.haml.deface @@ -1,3 +1,3 @@ / insert_bottom "[data-hook='admin_configurations_sidebar_menu']" -%li= link_to 'Content', main_app.edit_admin_content_path +%li= link_to t('admin.contents.edit.title'), main_app.edit_admin_content_path diff --git a/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface b/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface new file mode 100644 index 0000000000..f65ed9eeea --- /dev/null +++ b/app/overrides/spree/admin/shared/_configuration_menu/add_invoice_settings.html.haml.deface @@ -0,0 +1,4 @@ +// insert_bottom "[data-hook='admin_configurations_sidebar_menu']" + +%li + = link_to t('admin.invoice_settings.edit.invoice_settings'), main_app.edit_admin_invoice_settings_path diff --git a/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface b/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface index 561e59bf91..0b41db13d5 100644 --- a/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface +++ b/app/overrides/spree/admin/shipping_categories/index/add_temp_controlled_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='categories_header'] th:first-child" %th - Temperature Controlled + = t(:temperature_controlled) diff --git a/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface b/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface index 620f02f965..618d758898 100644 --- a/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface +++ b/app/overrides/spree/admin/shipping_methods/index/add_distributor_th.html.haml.deface @@ -1,4 +1,4 @@ / insert_after "[data-hook='admin_shipping_methods_index_headers'] th:first-child" %th - Distributors + = t(:products_distributor) diff --git a/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml b/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml index 17037d47e9..32b1c0b9a5 100644 --- a/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml +++ b/app/views/admin/accounts_and_billing_settings/_method_settings.html.haml @@ -1,10 +1,10 @@ .row .six.columns.alpha .field - = label :settings, :default_accounts_payment_method_id, t(:default_accounts_payment_method) + = label :settings, :default_accounts_payment_method_id, t('.default_accounts_payment_method') = collection_select(:settings, :default_accounts_payment_method_id, @payment_methods, :id, :name, { include_blank: true, selected: Spree::Config.default_accounts_payment_method_id}, { class: "select2 fullwidth" }) .six.columns.omega .field - = label :settings, :default_accounts_shipping_method_id, t(:default_accounts_shipping_method) + = label :settings, :default_accounts_shipping_method_id, t('.default_accounts_shipping_method') = collection_select(:settings, :default_accounts_shipping_method_id, @shipping_methods, :id, :name, { include_blank: true, selected: Spree::Config.default_accounts_shipping_method_id}, { class: "select2 fullwidth" }) diff --git a/app/views/admin/accounts_and_billing_settings/edit.html.haml b/app/views/admin/accounts_and_billing_settings/edit.html.haml index 83cfbbb76e..e17ceec637 100644 --- a/app/views/admin/accounts_and_billing_settings/edit.html.haml +++ b/app/views/admin/accounts_and_billing_settings/edit.html.haml @@ -1,7 +1,7 @@ = render :partial => 'spree/admin/shared/configuration_menu' - content_for :page_title do - = t(:accounts_and_billing) + = t('.accounts_and_billing') = render 'spree/shared/error_messages', target: @settings @@ -9,12 +9,12 @@ %fieldset.no-border-bottom %legend - = t(:admin_settings) + = t('.admin_settings') = form_for @settings, as: :settings, url: main_app.admin_accounts_and_billing_settings_path, :method => :put do |f| .row{ ng: { app: 'admin.accounts_and_billing_settings' } } .twelve.columns.alpha.omega .field - = f.label :accounts_distributor_id, t(:accounts_administration_distributor) + = f.label :accounts_distributor_id, t('.accounts_administration_distributor') = f.collection_select(:accounts_distributor_id, @distributors, :id, :name, { include_blank: true }, { class: "select2 fullwidth", 'watch-value-as' => "enterprise_id"}) = f.hidden_field :default_accounts_payment_method_id, value: '' @@ -25,18 +25,16 @@ .six.columns.alpha %fieldset.no-border-bottom %legend - =t :update_invoice + = t('.update_invoice') = f.check_box :auto_update_invoices - = f.label :auto_update_invoices, - t(:auto_update_invoices) + = f.label :auto_update_invoices, t('.auto_update_invoices') .six.columns.omega %fieldset.no-border-bottom %legend - =t :finalise_invoice + = t('.finalise_invoice') = f.check_box :auto_finalize_invoices - = f.label :auto_finalize_invoices, - t(:auto_finalise_invoices) + = f.label :auto_finalize_invoices, t('.auto_finalise_invoices') .row .twelve.columns.alpha.omega.form-buttons{"data-hook" => "buttons"} @@ -44,36 +42,35 @@ %fieldset.no-border-bottom %legend - =t :manually_run_task + =t('.manually_run_task') .row .six.columns.alpha.step.text-center .form-buttons{"data-hook" => "buttons"} - =link_to_with_icon "icon-undo", - t(:update_user_invoices) , - main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "update_account_invoices" }), - class: "button fullwidth" + = link_to_with_icon "icon-undo", t('.update_user_invoices'), + main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "update_account_invoices" }), + class: "button fullwidth" %br - if @update_account_invoices_job %p.text-center - if @update_account_invoices_job.run_at < Time.zone.now - =t :in_progress + = t(:in_progress) %br - =t :started_at + = t(:started_at) - else %strong - =t :queued + = t(:queued) %br - =t :Scheduled_for + = t(:scheduled_for) = @update_account_invoices_job.run_at - else %p.explanation - =t :update_user_invoice_explained + = t('.update_user_invoice_explained') .six.columns.omega.step.text-center .form-buttons{"data-hook" => "buttons"} - =link_to_with_icon "icon-ok-sign", t(:finalise_user_invoices ), + =link_to_with_icon "icon-ok-sign", t('.finalise_user_invoices'), main_app.start_job_admin_accounts_and_billing_settings_path(job: { name: "finalize_account_invoices" }), class: "button fullwidth" @@ -83,15 +80,15 @@ %p.text-center - if @finalize_account_invoices_job.run_at < Time.zone.now %strong - =t :in_progress + = t(:in_progress) %br - =t :started_at + = t(:started_at) - else %strong - =t :queued + = t(:queued) %br - =t :scheduled_for + = t(:scheduled_for) = @finalize_account_invoices_job.run_at - else %p.explanation - =t :finalise_user_invoice_explained + = t('.finalise_user_invoice_explained') diff --git a/app/views/admin/business_model_configuration/edit.html.haml b/app/views/admin/business_model_configuration/edit.html.haml index 04ee47e45d..29139d78bf 100644 --- a/app/views/admin/business_model_configuration/edit.html.haml +++ b/app/views/admin/business_model_configuration/edit.html.haml @@ -4,57 +4,58 @@ = "ng-app='admin.businessModelConfiguration'" - content_for :page_title do - %h1.page-title= t(:business_model_configuration) - %a{ 'ofn-with-tip' => "Configure the rate at which shops will be charged each month for use of the Open Food Network." } What's this? + %h1.page-title= t('.business_model_configuration') + %a{ 'ofn-with-tip' => t('.business_model_configuration_tip') } + = t('admin.whats_this') = render 'spree/shared/error_messages', target: @settings .row{ ng: { controller: "BusinessModelConfigCtrl" } } .five.columns.omega %fieldset.no-border-bottom - %legend=t(:bill_calculation_settings) + %legend=t('.bill_calculation_settings') %p - Adjust the amount that enterprises will be billed each month for use of the OFN. + = t('.bill_calculation_settings_tip') %br = form_for @settings, as: :settings, url: main_app.admin_business_model_configuration_path, :method => :put do |f| .row .three.columns.alpha - = f.label :shop_trial_length_days, t(:shop_trial_length) - %span.icon-question-sign{'ofn-with-tip' => "The length of time (in days) that enterprises who are set up as shops can run as a trial period."} + = f.label :shop_trial_length_days, t('.shop_trial_length') + %span.icon-question-sign{'ofn-with-tip' => t('.shop_trial_length_tip')} .two.columns.omega = f.number_field :shop_trial_length_days, min: 0.0, step: 1.0, class: "fullwidth" .row .three.columns.alpha - = f.label :account_invoices_monthly_fixed, t(:fixed_monthly_charge) - %span.icon-question-sign{'ofn-with-tip' => "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)."} + = f.label :account_invoices_monthly_fixed, t('.fixed_monthly_charge') + %span.icon-question-sign{'ofn-with-tip' => t('.fixed_monthly_charge_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol = f.number_field :account_invoices_monthly_fixed, min: 0.0, class: "fullwidth", 'watch-value-as' => 'fixed' .row .three.columns.alpha - = f.label :account_invoices_monthly_rate, t(:percentage_of_turnover) - %span.icon-question-sign{'ofn-with-tip' => "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill."} + = f.label :account_invoices_monthly_rate, t('.percentage_of_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.percentage_of_turnover_tip')} .two.columns.omega = f.number_field :account_invoices_monthly_rate, min: 0.0, max: 1.0, step: 0.01, class: "fullwidth", 'watch-value-as' => 'rate' .row .three.columns.alpha - = f.label :account_invoices_monthly_cap, t(:monthly_cap_excl_tax) - %span.icon-question-sign{'ofn-with-tip' => "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month."} + = f.label :account_invoices_monthly_cap, t('.monthly_cap_excl_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.monthly_cap_excl_tax_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol = f.number_field :account_invoices_monthly_cap, min: 0.0, class: "fullwidth", 'watch-value-as' => 'cap' .row .three.columns.alpha - = f.label :account_invoices_tax_rate, t(:tax_rate) - %span.icon-question-sign{'ofn-with-tip' => "Tax rate that applies to the the monthly bill that enterprises are charged for using the system."} + = f.label :account_invoices_tax_rate, t('.tax_rate') + %span.icon-question-sign{'ofn-with-tip' => t('.tax_rate_tip')} .two.columns.omega = f.number_field :account_invoices_tax_rate, min: 0.0, max: 1.0, step: 0.01, class: "fullwidth", 'watch-value-as' => 'taxRate' .row .three.columns.alpha - = f.label :minimum_billable_turnover, t(:minimum_monthly_billable_turnover) - %span.icon-question-sign{'ofn-with-tip' => "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate."} + = f.label :minimum_billable_turnover, t('.minimum_monthly_billable_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.minimum_monthly_billable_turnover_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol @@ -69,35 +70,35 @@ .five.columns.alpha %fieldset.no-border-bottom - %legend=t(:example_bill_calculator) + %legend= t('.example_bill_calculator') %p - Alter the example turnover to visualise the effect of the settings to the left. + = t('.example_bill_calculator_legend') %br .row .three.columns.alpha - = label_tag :turnover, t(:example_monthly_turnover) - %span.icon-question-sign{'ofn-with-tip' => "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below."} + = label_tag :turnover, t('.example_monthly_turnover') + %span.icon-question-sign{'ofn-with-tip' => t('.example_monthly_turnover_tip')} .two.columns.omega .input-symbol.before %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'turnover', type: "number", ng: { model: 'turnover' } } .row .three.columns.alpha - = label_tag :cap_reached, t(:cap_reached?) - %span.icon-question-sign{'ofn-with-tip' => "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided."} + = label_tag :cap_reached, t('.cap_reached?') + %span.icon-question-sign{'ofn-with-tip' => t('.cap_reached?_tip')} .two.columns.omega %input.fullwidth{ id: 'cap_reached', type: "text", readonly: true, ng: { value: 'capReached()' } } .row .three.columns.alpha - = label_tag :included_tax, t(:included_tax) - %span.icon-question-sign{'ofn-with-tip' => "The total tax included in the example monthly bill, given the settings and the turnover provided."} + = label_tag :included_tax, t('.included_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.included_tax_tip')} .two.columns.omega %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'included_tax', type: "text", readonly: true, ng: { value: 'includedTax()' } } .row .three.columns.alpha - = label_tag :total_incl_tax, t(:total_monthly_bill_incl_tax) - %span.icon-question-sign{'ofn-with-tip' => "The example total monthly bill with tax included, given the settings and the turnover provided."} + = label_tag :total_incl_tax, t('.total_monthly_bill_incl_tax') + %span.icon-question-sign{'ofn-with-tip' => t('.total_monthly_bill_incl_tax_tip')} .two.columns.omega %span= Spree::Money.currency_symbol %input.fullwidth{ id: 'total_incl_tax', type: "text", readonly: true, ng: { value: 'total()' } } diff --git a/app/views/admin/enterprises/_enterprise_user_index.html.haml b/app/views/admin/enterprises/_enterprise_user_index.html.haml index 4b777e127b..b4bc32d2ad 100644 --- a/app/views/admin/enterprises/_enterprise_user_index.html.haml +++ b/app/views/admin/enterprises/_enterprise_user_index.html.haml @@ -10,10 +10,9 @@ .row{ 'ng-if' => '!loaded' } .sixteen.columns.alpha#loading %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 LOADING ENTERPRISES + %h1= t('.loading_enterprises') .row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredEnterprises.length == 0'} - %h1#no_results No enterprises found. - + %h1#no_results= t('.no_enterprises_found') .row{ ng: { show: "loaded && filteredEnterprises.length > 0" } } %table.index#enterprises diff --git a/app/views/admin/enterprises/form/_about_us.html.haml b/app/views/admin/enterprises/form/_about_us.html.haml index 32550b711b..fdc9827e4f 100644 --- a/app/views/admin/enterprises/form/_about_us.html.haml +++ b/app/views/admin/enterprises/form/_about_us.html.haml @@ -14,4 +14,4 @@ -# ['html', 'insertImage', 'insertLink', 'insertVideo'] %text-angular{'ng-model' => 'Enterprise.long_description', 'id' => 'enterprise_long_description', 'name' => 'enterprise[long_description]', 'class' => 'text-angular', 'ta-toolbar' => "[['h1','h2','h3','h4','p'],['bold','italics','underline','clear'],['insertLink']]", - 'placeholder' => t('.desc_long_placeholder')} \ No newline at end of file + 'placeholder' => t('.desc_long_placeholder')} diff --git a/app/views/admin/enterprises/form/_business_details.html.haml b/app/views/admin/enterprises/form/_business_details.html.haml index 4015e51282..e14254ef5d 100644 --- a/app/views/admin/enterprises/form/_business_details.html.haml +++ b/app/views/admin/enterprises/form/_business_details.html.haml @@ -21,3 +21,13 @@ = f.radio_button :charges_sales_tax, false   = f.label :charges_sales_tax, t(:say_no), value: 'false' +.row + .alpha.three.columns + = f.label :display_invoice_logo, 'Display logo in invoices' + .omega.eight.columns + = f.check_box :display_invoice_logo +.row + .alpha.three.columns + = f.label :invoice_text, 'Add customized text at the end of invoices' + .omega.eight.columns + = f.text_area :invoice_text, style: "width: 100%; height: 100px;" diff --git a/app/views/admin/invoice_settings/edit.html.haml b/app/views/admin/invoice_settings/edit.html.haml new file mode 100644 index 0000000000..e134356927 --- /dev/null +++ b/app/views/admin/invoice_settings/edit.html.haml @@ -0,0 +1,19 @@ += render :partial => 'spree/admin/shared/configuration_menu' + +- content_for :page_title do + = t('.title') + += form_tag main_app.admin_invoice_settings_path, :method => :put do + + .field.align-center + = hidden_field_tag 'preferences[invoice_style2?]', '0' + = check_box_tag 'preferences[invoice_style2?]', '1', Spree::Config[:invoice_style2?] + = label_tag nil, t('.invoice_style2?') + + .field.align-center + = hidden_field_tag 'preferences[enable_receipt_printing?]', '0' + = check_box_tag 'preferences[enable_receipt_printing?]', '1', Spree::Config[:enable_receipt_printing?] + = label_tag nil, t('.enable_receipt_printing?') + + .form-buttons{"data-hook" => "buttons"} + = button t(:update), 'icon-refresh' diff --git a/app/views/checkout/_shipping_ship_address.html.haml b/app/views/checkout/_shipping_ship_address.html.haml index fa87eef2ff..7b4db0d54c 100644 --- a/app/views/checkout/_shipping_ship_address.html.haml +++ b/app/views/checkout/_shipping_ship_address.html.haml @@ -3,26 +3,26 @@ %div.visible{"ng-if" => "!Checkout.ship_address_same_as_billing"} .row .small-6.columns - = validated_input "First Name", "order.ship_address.firstname", "ofn-focus" => "accordion['shipping']" + = validated_input t(:first_name), "order.ship_address.firstname", "ofn-focus" => "accordion['shipping']" .small-6.columns - = validated_input "Last Name", "order.ship_address.lastname" + = validated_input t(:last_name), "order.ship_address.lastname" .row .small-12.columns - = validated_input "Address", "order.ship_address.address1" + = validated_input t(:address), "order.ship_address.address1" .row .small-12.columns - = validated_input "Address (contd.)", "order.ship_address.address2", required: false + = validated_input t(:address2), "order.ship_address.address2", required: false .row .small-6.columns - = validated_input "City", "order.ship_address.city" + = validated_input t(:city), "order.ship_address.city" .small-6.columns - = validated_select "State", "order.ship_address.state_id", checkout_state_options(:shipping) + = validated_select t(:state), "order.ship_address.state_id", checkout_state_options(:shipping) .row .small-6.columns - = validated_input "Postcode", "order.ship_address.zipcode" + = validated_input t(:postcode), "order.ship_address.zipcode" .small-6.columns.right - = validated_select "Country", "order.ship_address.country_id", checkout_country_options + = validated_select t(:country), "order.ship_address.country_id", checkout_country_options .row .small-6.columns - = validated_input "Phone", "order.ship_address.phone" + = validated_input t(:phone), "order.ship_address.phone" diff --git a/app/views/registration/_modal.html.haml b/app/views/registration/_modal.html.haml new file mode 100644 index 0000000000..5fa1da9296 --- /dev/null +++ b/app/views/registration/_modal.html.haml @@ -0,0 +1,11 @@ +%script{ type: "text/ng-template", id: "registration.html" } + %div#registration-modal{"ng-controller" => "RegistrationCtrl"} + %div{ ng: { show: "currentStep() == 'introduction'" } } + %ng-include{ src: "'registration/introduction.html'" } + %div{ ng: { repeat: 'step in steps', show: "currentStep() == step" } } + %ng-include{ src: "'registration/'+ step + '.html'" } + %div{ ng: { show: "currentStep() == 'finished'" } } + %ng-include{ src: "'registration/finished.html'" } + + %a.close-reveal-modal{"ng-click" => "$close()"} + %i.ofn-i_009-close diff --git a/app/views/registration/index.html.haml b/app/views/registration/index.html.haml index fdeef18534..4f23ac8700 100644 --- a/app/views/registration/index.html.haml +++ b/app/views/registration/index.html.haml @@ -5,4 +5,10 @@ = inject_available_countries = inject_enterprise_attributes +- steps = %w{about contact details finished images introduction} +- steps += %w{limit_reached logo promo social steps type} +- steps.each do |step| + = render partial: "registration/steps/#{step}" += render "modal" + %div{ "ng-controller" => "RegistrationCtrl" } diff --git a/app/views/registration/steps/_about.html.haml b/app/views/registration/steps/_about.html.haml new file mode 100644 index 0000000000..529fdebea3 --- /dev/null +++ b/app/views/registration/steps/_about.html.haml @@ -0,0 +1,57 @@ +%script{ type: "text/ng-template", id: "registration/about.html" } + .container#registration-about + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'enterprise_about_headline' | t}} + %h5 + {{'enterprise_about_message' | t}} + %span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } } + {{ enterprise.name }} + + %form{ name: 'about', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('images',about)" } } + .row + .small-12.columns + .alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } } + %h6{ "ng-bind" => "'enterprise_success' | t:{enterprise: enterprise.name}" } + %span {{'enterprise_registration_exit_message' | t}} + %a.close{ ng: { click: "close()" } } × + + .small-12.large-8.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_description' } {{'enterprise_description' | t}}: + %input.chunky{ id: 'enterprise_description', placeholder: "{{'enterprise_description_placeholder' | t}}", ng: { model: 'enterprise.description' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_long_desc' } {{'enterprise_long_desc' | t}}: + %textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "{{'enterprise_long_desc_placeholder' | t}}", ng: { model: 'enterprise.long_description' } } + %small{ "ng-bind" => "'enterprise_long_desc_length' | t:{num: enterprise.long_description.length}" } + .small-12.large-4.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_abn' } {{'enterprise_abn' | t}}: + %input.chunky{ id: 'enterprise_abn', placeholder: "{{'enterprise_abn_placeholder' | t}}", ng: { model: 'enterprise.abn' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_acn' } {{'enterprise_acn' | t}}: + %input.chunky{ id: 'enterprise_acn', placeholder: "{{'enterprise_acn_placeholder' | t}}", 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' } {{'say_yes' | t}} + %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' } {{'say_no' | t}} + %span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } } + {{'enterprise_tax_required' | t}} + + .row.buttons.pad-top + .small-12.columns + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_contact.html.haml b/app/views/registration/steps/_contact.html.haml new file mode 100644 index 0000000000..3b7d43ae72 --- /dev/null +++ b/app/views/registration/steps/_contact.html.haml @@ -0,0 +1,32 @@ +%script{ type: "text/ng-template", id: "registration/contact.html" } + .container#registration-contact + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_greeting' | t}} + %h5{ "ng-bind" => "'who_is_managing_enterprise' | t:{enterprise: enterprise.name}" } + + %form{ name: 'contact', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('type',contact)" } } + .row.content + .small-12.medium-12.large-7.columns + .row + .small-12.columns.field + %label{ for: 'enterprise_contact' } {{'enterprise_contact' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_contact', name: 'contact', required: true, placeholder: "Contact Name", ng: { model: 'enterprise.contact' } } + %span.error.small-12.columns{ ng: { show: "contact.contact.$error.required && submitted" } } + {{'enterprise_contact_required' | t}} + .row + .small-12.columns.field + %label{ for: 'enterprise_email_address' } {{'enterprise_email_address' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_email_address', name: 'email_address', type: 'email', placeholder: "eg. charlie@thefarm.com", ng: { model: 'enterprise.email_address' } } + .row + .small-12.columns.field + %label{ for: 'enterprise_phone' } {{'enterprise_phone' | t}}: + %input.chunky.small-12.columns{ id: 'enterprise_phone', name: 'phone', placeholder: "eg. (03) 1234 5678", ng: { model: 'enterprise.phone' } } + .small-12.medium-12.large-5.hide-for-small-only + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('details')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_details.html.haml b/app/views/registration/steps/_details.html.haml new file mode 100644 index 0000000000..dd3ee65085 --- /dev/null +++ b/app/views/registration/steps/_details.html.haml @@ -0,0 +1,65 @@ +%script{ type: "text/ng-template", id: "registration/details.html" } + .container#registration-details + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_detail_headline' | t}} + %h5{ ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}} + %h5{ ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_producer' | t}} + + %form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } } + + .row + .small-12.medium-9.large-12.columns.end + .field + %label{ for: 'enterprise_name', ng: { if: "::enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}} + %label{ for: 'enterprise_name', ng: { if: "::enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}} + %input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } } + %span.error{ ng: { show: "details.name.$error.required && submitted" } } + {{'registration_detail_name_error' | t}} + + .row + .small-12.medium-9.large-6.columns + .field + %label{ for: 'enterprise_address' } {{'registration_detail_address1' | t}} + %input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "{{'registration_detail_address1_placeholder' | t}}", required: true, ng: { model: 'enterprise.address.address1' } } + %span.error{ ng: { show: "details.address1.$error.required && submitted" } } + {{'registration_detail_address1_error' | t}} + .field + %label{ for: 'enterprise_address2' } {{'registration_detail_address2' | t}} + %input.chunky{ id: 'enterprise_address2', name: 'address2', required: false, placeholder: "", required: false, ng: { model: 'enterprise.address.address2' } } + + .small-12.medium-9.large-6.columns.end + .row + .small-12.medium-8.large-8.columns + .field + %label{ for: 'enterprise_city' } {{'registration_detail_suburb' | t}} + %input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "{{'registration_detail_suburb_placeholder' | t}}", ng: { model: 'enterprise.address.city' } } + %span.error{ ng: { show: "details.city.$error.required && submitted" } } + {{'registration_detail_suburb_error' | t}} + .small-12.medium-4.large-4.columns + .field + %label{ for: 'enterprise_zipcode' } {{'registration_detail_postcode' | t}} + %input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "{{'registration_detail_postcode_placeholder' | t}}", ng: { model: 'enterprise.address.zipcode' } } + %span.error{ ng: { show: "details.zipcode.$error.required && submitted" } } + {{'registration_detail_postcode_error' | t}} + .row + .small-12.medium-4.large-4.columns + .field + %label{ for: 'enterprise_state' } {{'registration_detail_state' | t}} + %select.chunky{ id: 'enterprise_state', name: 'state', ng: { model: 'enterprise.address.state_id', options: 's.id as s.abbr for s in enterprise.country.states', show: 'countryHasStates()', required: 'countryHasStates()' } } + %span.error{ ng: { show: "details.state.$error.required && submitted" } } + {{'registration_detail_state_error' | t}} + .small-12.medium-8.large-8.columns + .field + %label{ for: 'enterprise_country' } {{'registration_detail_country' | t}} + %select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { model: 'enterprise.country', options: 'c as c.name for c in countries' } } + %span.error{ ng: { show: "details.country.$error.required && submitted" } } + {{'registration_detail_country_error' | t}} + + + .row.buttons + .small-12.columns + %hr + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_finished.html.haml b/app/views/registration/steps/_finished.html.haml new file mode 100644 index 0000000000..bae5397a29 --- /dev/null +++ b/app/views/registration/steps/_finished.html.haml @@ -0,0 +1,16 @@ +%script{ type: "text/ng-template", id: "registration/finished.html" } + .container#registration-finished + .row + .small-12.columns.pad-top + %header + %h2 {{'registration_finished_headline' | t}} + .panel.callout + %p{ "ng-bind" => "'registration_finished_thanks' | t:{enterprise: enterprise.name}" } + %p {{'registration_finished_login' | t}} + .row + .small-12.columns.text-center + %h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" } + + %p{ "ng-bind-html" => "'registration_finished_activate_instruction_html' | t:{email: enterprise.email}"} + + %a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} > diff --git a/app/views/registration/steps/_images.html.haml b/app/views/registration/steps/_images.html.haml new file mode 100644 index 0000000000..f888bd8165 --- /dev/null +++ b/app/views/registration/steps/_images.html.haml @@ -0,0 +1,23 @@ +%script{ type: "text/ng-template", id: "registration/images.html" } + .container#registration-images{ 'nv-file-drop' => true, uploader: "imageUploader", options:"{ alias: imageStep }", ng: { controller: "EnterpriseImageCtrl" } } + %ng-include{ src: "'registration/steps.html'" } + .row + .small-12.columns + %header + %h2 {{'registration_images_headline' | t}} + %h5 {{'registration_images_description' | t}} + + %form{ name: 'images', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "select('social')" } } + .row{ ng: { repeat: 'image_step in imageSteps', show: "imageStep == image_step" } } + %ng-include{ src: "'registration/'+ image_step + '.html'" } + + .row.buttons.pad-top{ ng: { if: "imageStep == 'logo'" } } + .small-12.columns + %input.button.secondary{ type: "button", value: "Back", ng: { click: "select('about')" } } +   + %input.button.primary.right{ type: "button", value: "Continue", ng: { click: "imageSelect('promo')" } } + + .row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } } + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "imageSelect('logo')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_introduction.html.haml b/app/views/registration/steps/_introduction.html.haml new file mode 100644 index 0000000000..c663886a03 --- /dev/null +++ b/app/views/registration/steps/_introduction.html.haml @@ -0,0 +1,46 @@ +%script{ type: "text/ng-template", id: "registration/introduction.html" } + .row + .small-12.columns + %header + %h2 {{'registration_greeting' | t}} + %h4 + %small + %i.ofn-i_040-hub + {{'registration_intro' | t}} + + .row{ 'data-equalizer' => true } + .small-12.medium-12.large-6.columns.pad-top{ 'data-equalizer-watch' => true } + %h5 {{'registration_checklist' | t}}: + %ul.check-list + %li + {{'registration_time' | t}} + %li + {{'registration_enterprise_address' | t}} + %li + {{'registration_contact_details' | t}} + %li + {{'registration_logo' | t}} + %li + {{'registration_promo_image' | t}} + %li + {{'registration_about_us' | t}} + + .small-9.medium-8.large-5.columns.pad-top.end{ 'data-equalizer-watch' => true} + %h5 + {{'registration_outcome_headline' | t}} + %p{ "ng-bind-html" => "t('registration_outcome1_html')" } + %p {{'registration_outcome2' | t}} + %p {{'registration_outcome3' | t}} + + .row{'ng-init' => "tos_required=#{Spree::Config.enterprises_require_tos}" } + %hr + .small-12.columns{'ng-hide' => '!tos_required' } + %p.tos-message + #{t(:enterprise_tos_message)} + %a{href: "#{Spree::Config.enterprise_tos_link}", target: "_blank" } #{t(:enterprise_tos_link_text)} + %p.tos-checkbox + %input{ type: 'checkbox', name: 'accept_terms', id: 'accept_terms', ng: { model: "tos_accepted" } } + %label{for: "accept_terms"} #{t(:enterprise_tos_agree)} + + .small-12.columns + %input.button.primary.left{ type: "button", value: "{{'registration_action' | t}}", ng: { click: "select('details')", disabled: "tos_required && !tos_accepted", model: "tos_accepted"} } diff --git a/app/views/registration/steps/_limit_reached.html.haml b/app/views/registration/steps/_limit_reached.html.haml new file mode 100644 index 0000000000..44f3b53f22 --- /dev/null +++ b/app/views/registration/steps/_limit_reached.html.haml @@ -0,0 +1,17 @@ +%script{ type: "text/ng-template", id: "registration/limit_reached.html" } + .row + .small-12.columns + %header + %h2 {{'limit_reached_headline' | t}} + %h4 {{'limit_reached_message' | t}} + .row + .small-12.medium-3.large-2.columns.text-right.hide-for-small-only + %img{:src => "/assets/potatoes.png"} + .small-12.medium-9.large-10.columns + %p + {{'limit_reached_text' | t}} + %strong Open Food Network. + .row + .small-12.columns + %hr + %input.button.primary{ type: "button", value: "{{'limit_reached_action' | t}}", ng: { click: "close()" } } diff --git a/app/views/registration/steps/_logo.html.haml b/app/views/registration/steps/_logo.html.haml new file mode 100644 index 0000000000..3d1effdf93 --- /dev/null +++ b/app/views/registration/steps/_logo.html.haml @@ -0,0 +1,46 @@ +%script{ type: "text/ng-template", id: "registration/logo.html" } + .small-12.medium-12.large-6.columns + .row + .small-12.columns.center + .row + .small-12.columns.center + %h4 + {{'select_logo' | t}} + .row + .small-12.columns.center + %span.small + {{'logo_tip' | t}} + .row.pad-top + .small-12.columns + .image-select.small-12.columns + %label.small-12.columns.button{ for: 'image-select' } {{'logo_label' | t}} + %input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' } + .row.show-for-large-up + .large-12.columns + %span#or.large-12.columns + {{'action_or' | t}} + .row.show-for-large-up + .large-12.columns + #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } + {{'logo_drag' | t}} + .small-12.medium-12.large-6.columns + .row + .small-12.columns.center + .row + .small-12.columns.center + %h4 + {{'review_logo' | t}} + .row + .small-12.columns.center + %span.small + {{'review_logo_tip' | t}} + .row.pad-top + .small-12.columns.center + #image-placeholder.logo + %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } + .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } + {{'logo_placeholder' | t}} + .loading{ ng: { hide: "!imageUploader.isUploading" } } + %img.spinner{ src: "/assets/spinning-circles.svg" } + %br/ + {{'uploading' | t}} diff --git a/app/views/registration/steps/_promo.html.haml b/app/views/registration/steps/_promo.html.haml new file mode 100644 index 0000000000..0b224e1f64 --- /dev/null +++ b/app/views/registration/steps/_promo.html.haml @@ -0,0 +1,44 @@ +%script{ type: "text/ng-template", id: "registration/promo.html" } + .small-12.medium-12.large-12.columns + .row + .small-12.columns.center + %h4 + {{'select_promo_image' | t}} + .row + .small-12.medium-12.large-5.columns.center + .row + .small-12.columns.center + %span.small + {{'promo_image_tip' | t}} + .row.pad-top + .small-12.columns + .image-select.small-12.columns + %label.small-12.columns.button{ for: 'image-select' } {{'promo_image_label' | t}} + %input#image-select{ type: 'file', hidden: true, 'nv-file-select' => true, uploader: "imageUploader", options: '{ alias: imageStep }' } + .large-2.columns + %span#or.horizontal.large-12.columns + {{'action_or' | t}} + .large-5.columns + #image-over{ 'nv-file-over' => true, uploader: "imageUploader" } + {{'promo_image_drag' | t}} + .small-12.medium-12.large-12.columns.pad-top + .row + .small-12.columns.center + %h4 + {{'review_promo_image' | t}} + .row + .small-12.columns.center + .row + .small-12.columns.center + %span.small + {{'review_promo_image_tip' | t}} + .row.pad-top + .small-12.columns.center + #image-placeholder.promo + %img{ ng: { show: "imageSrc() && !imageUploader.isUploading", src: '{{ imageSrc() }}' } } + .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } + {{'promo_image_placeholder' | t}} + .loading{ ng: { hide: "!imageUploader.isUploading" } } + %img.spinner{ src: "/assets/spinning-circles.svg" } + %br/ + {{'uploading' | t}} diff --git a/app/views/registration/steps/_social.html.haml b/app/views/registration/steps/_social.html.haml new file mode 100644 index 0000000000..edbdd94dd9 --- /dev/null +++ b/app/views/registration/steps/_social.html.haml @@ -0,0 +1,44 @@ +%script{ type: "text/ng-template", id: "registration/social.html" } + .container#registration-social + %ng-include{ src: "'registration/steps.html'" } + + .row + .small-12.columns + %header + %h2 {{'enterprise_final_step' | t}} + %h5{ "ng-bind" => "'enterprise_social_text' | t:{enterprise: enterprise.name}" } + + %form{ name: 'social', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('finished',social)" } } + .row.content + .small-12.large-7.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_website' } {{'website' | t}}: + %input.chunky{ id: 'enterprise_website', placeholder: "{{'website_placeholder' | t}}", ng: { model: 'enterprise.website' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_facebook' } {{'facebook' | t}}: + %input.chunky{ id: 'enterprise_facebook', placeholder: "{{'facebook_placeholder' | t}}", ng: { model: 'enterprise.facebook' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_linkedin' } {{'linkedin' | t}}: + %input.chunky{ id: 'enterprise_linkedin', placeholder: "{{'linkedin_placeholder' | t}}", ng: { model: 'enterprise.linkedin' } } + .small-12.large-5.columns + .row + .small-12.columns + .field + %label{ for: 'enterprise_twitter' } {{'twitter' | t}}: + %input.chunky{ id: 'enterprise_twitter', placeholder: "{{'twitter_placeholder' | t}}", ng: { model: 'enterprise.twitter' } } + .row + .small-12.columns + .field + %label{ for: 'enterprise_instagram' } {{'instagram' | t}}: + %input.chunky{ id: 'enterprise_instagram', placeholder: "{{'instagram_placeholder' | t}}", ng: { model: 'enterprise.instagram' } } + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('images')" } } + %input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" } diff --git a/app/views/registration/steps/_steps.html.haml b/app/views/registration/steps/_steps.html.haml new file mode 100644 index 0000000000..7ea0412929 --- /dev/null +++ b/app/views/registration/steps/_steps.html.haml @@ -0,0 +1,4 @@ +%script{ type: "text/ng-template", id: "registration/steps.html" } + .row#progress-bar + .small-12.medium-2.columns.item{ ng: { repeat: 'step in steps', class: "{active: (currentStep() == step),'show-for-medium-up': (currentStep() != step)}" } } + {{ $index+1 + ". " + step }} diff --git a/app/views/registration/steps/_type.html.haml b/app/views/registration/steps/_type.html.haml new file mode 100644 index 0000000000..4c93c441f4 --- /dev/null +++ b/app/views/registration/steps/_type.html.haml @@ -0,0 +1,48 @@ +%script{ type: "text/ng-template", id: "registration/type.html" } + .container#registration-type + + %ng-include{ src: "'registration/steps.html'" } + + .row + .small-12.columns + %header + %h2{ "ng-bind" => "'registration_type_headline' | t:{enterprise: enterprise.name}" } + %h4 + {{'registration_type_question' | t}} + + %form{ name: 'type', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "create(type)" } } + .row#enterprise-types{ 'data-equalizer' => true, ng: { if: "::enterprise.type != 'own'" } } + .small-12.columns.field + .row + .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } + %a.btnpanel#producer-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = true", class: "{selected: enterprise.is_primary_producer}" } } + %i.ofn-i_059-producer + %h4 {{'registration_type_producer' | t}} + + .small-12.medium-6.large-6.columns{ 'data-equalizer-watch' => true } + %a.btnpanel#hub-panel{ href: "#", ng: { click: "enterprise.is_primary_producer = false", class: "{selected: enterprise.is_primary_producer == false}" } } + %i.ofn-i_063-hub + %h4 {{'registration_type_no_producer' | t}} + + .row + .small-12.columns + %input.chunky{ id: 'enterprise_is_primary_producer', name: 'is_primary_producer', hidden: true, required: true, ng: { model: 'enterprise.is_primary_producer' } } + %span.error{ ng: { show: "type.is_primary_producer.$error.required && submitted" } } + {{'registration_type_error' | t}} + .row + .small-12.columns + .panel.callout + .left + %i.ofn-i_013-help +   + %p {{'registration_type_producer_help' | t}} + .panel.callout + .left + %i.ofn-i_013-help +   + %p {{'registration_type_no_producer_help' | t}} + + .row.buttons + .small-12.columns + %input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('contact')" } } + %input.button.primary.right{ type: "submit", value: "{{'create_profile' | t}}" } diff --git a/app/views/spree/admin/orders/_invoice_table2.html.haml b/app/views/spree/admin/orders/_invoice_table2.html.haml new file mode 100644 index 0000000000..0941904d8b --- /dev/null +++ b/app/views/spree/admin/orders/_invoice_table2.html.haml @@ -0,0 +1,58 @@ +%table.order-summary{:width => "100%"} + %thead + %tr + %th{:align => "left"} + %h5= t(:invoice_column_item) + %th{:align => "right", :width => "15%"} + %h5= t(:invoice_column_qty) + %th{:align => "right", :width => "15%"} + %h5= @order.has_taxes_included ? t(:invoice_column_unit_price_with_taxes) : t(:invoice_column_unit_price_without_taxes) + %th{:align => "right", :width => "15%"} + %h5= @order.has_taxes_included ? t(:invoice_column_price_with_taxes) : t(:invoice_column_price_without_taxes) + - if @order.total_tax > 0 + %th{:align => "right", :width => "15%"} + %h5= t(:invoice_column_tax_rate) + %tbody + - @order.line_items.sort_by{ |li| li.product.name }.each do |item| + %tr + %td + = render 'spree/shared/line_item_name', line_item: item + %td{:align => "right"} + = item.quantity + %td{:align => "right"} + = item.single_display_amount_with_adjustments + %td{:align => "right"} + = item.display_amount_with_adjustments + - if @order.total_tax > 0 + %td{:align => "right"} + = display_line_item_tax_rates(item) + - checkout_adjustments_for(@order, exclude: [:line_item]).reject{ |a| a.amount == 0 }.reverse_each do |adjustment| + %tr + %td + %strong= "#{raw(adjustment.label)}" + %td{:align => "right"} + %td{:align => "right"} + %td{:align => "right"} + = adjustment.display_amount + - if @order.total_tax > 0 + %td{:align => "right"} + = display_adjustment_tax_rates(adjustment) + %tfoot + %tr + %td{:align => "right", :colspan => "3"} + %strong= @order.has_taxes_included ? t(:total_incl_tax) : t(:total_excl_tax) + %td{:align => "right", :colspan => "2"} + %strong= @order.has_taxes_included ? @order.display_total : display_checkout_total_less_tax(@order) + - display_checkout_taxes_hash(@order).each do |tax_rate, tax_value| + %tr + %td{:align => "right", :colspan => "3"} + = t(:tax_total, rate: tax_rate) + %td{:align => "right", :colspan => "2"} + = tax_value + %tr + %td{:align => "right", :colspan => "3"} + = @order.has_taxes_included ? t(:total_excl_tax) : t(:total_incl_tax) + %td{:align => "right", :colspan => "2"} + = @order.has_taxes_included ? display_checkout_total_less_tax(@order) : @order.display_total +%p +   diff --git a/app/views/spree/admin/orders/invoice.html.haml b/app/views/spree/admin/orders/invoice.html.haml index 0913ee27db..627032fd39 100644 --- a/app/views/spree/admin/orders/invoice.html.haml +++ b/app/views/spree/admin/orders/invoice.html.haml @@ -1,6 +1,5 @@ = wicked_pdf_stylesheet_link_tag "mail/all" - %table{:width => "100%"} %tbody %tr{ valign: "top" } @@ -49,4 +48,8 @@ %p   +- if @order.distributor.invoice_text.present? + %p + = @order.distributor.invoice_text + = render 'spree/order_mailer/payment' diff --git a/app/views/spree/admin/orders/invoice2.html.haml b/app/views/spree/admin/orders/invoice2.html.haml new file mode 100644 index 0000000000..89f28ab308 --- /dev/null +++ b/app/views/spree/admin/orders/invoice2.html.haml @@ -0,0 +1,71 @@ += wicked_pdf_stylesheet_link_tag "mail/all" + + +%table{:width => "100%"} + %tbody + %tr{ valign: "top" } + %td{ :align => "left" } + %h4 + = t :tax_invoice + - if @order.distributor.display_invoice_logo? && @order.distributor.logo.present? + %td{ :align => "right", rowspan: 2 } + = wicked_pdf_image_tag @order.distributor.logo(:small), width: 150, height: 150 + %tr{ valign: "top" } + %td{ :align => "left" } + %strong= @order.distributor.name + %br + = @order.distributor.address.address_part1 + %br + = @order.distributor.address.address_part2 + %br + = @order.distributor.email_address + - if @order.distributor.phone.present? + %br + = @order.distributor.phone + - if @order.distributor.abn.present? + %br + = "#{t :abn} #{@order.distributor.abn}" + - if @order.distributor.acn.present? + %br + = "#{t :acn} #{@order.distributor.acn}" + %tr{ valign: "top" } + %td{ :align => "left", colspan: 2 }   + %tr{ valign: "top" } + %td{ :align => "left" } + %br + = t :invoice_issued_on + = l Time.zone.now.to_date + %br + = t :date_of_transaction + = l @order.completed_at.to_date + %br + = t :order_number + = @order.number + %td{ :align => "right" } + = t :invoice_billing_address + %br + %strong= @order.ship_address.full_name + - if @order.customer.code.present? + %br + = "Code: #{@order.customer.code}" + %br + = @order.ship_address.address_part1 + %br + = @order.ship_address.address_part2 + += render 'spree/admin/orders/invoice_table2' + +- if @order.special_instructions.present? + %p.callout + %strong + = t :customer_instructions + %p + %em= @order.special_instructions + %p +   + +- if @order.distributor.invoice_text.present? + %p + = @order.distributor.invoice_text + += render 'spree/order_mailer/payment' diff --git a/app/views/spree/admin/orders/ticket.html.haml b/app/views/spree/admin/orders/ticket.html.haml new file mode 100644 index 0000000000..53f224cff1 --- /dev/null +++ b/app/views/spree/admin/orders/ticket.html.haml @@ -0,0 +1,79 @@ +!!! Basic +%html + %head + + = javascript_include_tag "shared/jquery-1.8.0.js" + = javascript_include_tag "qz/qz-tray.js" + = javascript_include_tag "qz/sha-256.min.js" + = javascript_include_tag "qz/rsvp-3.1.0.min.js" + = javascript_include_tag "qz/jsrsasign-latest-all-min.js" + :javascript + var printData = [ + '\x1B' + '\x40', // init + '\x1B' + '\x74' + '\x10', + '\x1B' + '\x61' + '\x31', // center align + '\x1B' + '\x21' + '\x30', // em mode on + '#{@order.distributor.name}' + '\x0A', + '\x1B' + '\x21' + '\x0A' + '\x1B' + '\x45' + '\x0A', // em mode off + '\x0A', + '#{@order.distributor.address.address_part1}' + '\x0A', // text and line break + '#{@order.distributor.address.address_part2}' + '\x0A', + '#{@order.distributor.email}' + '\x0A', + '\x0A', // line break + '\x1B' + '\x61' + '\x32', // right align + '#{l Time.zone.now.to_date}' + '\x0A', + '#{@order.number}' + '\x0A', + '\x1B' + '\x61' + '\x30', // left align + '\x0A', + '\x1B' + '\x4D' + '\x31', // small text + "#{'%6s %-23s%12s%12s' % + [t(:ticket_column_qty), + t(:ticket_column_item), + t(:ticket_column_unit_price), + t(:ticket_column_total_price)]}", + '\x0A', + '\x1B' + '\x4D' + '\x30', // normal text + '__________________________________________' + '\x0A', + "#{@order.line_items + .sort_by{ |line_item| line_item.product.name } + .map { |line_item| '%5d %-19.19s%8.8s%8.8s' % + [line_item.quantity, + line_item.product.name, + line_item.single_display_amount_with_adjustments.money.format(symbol: false), + line_item.display_amount_with_adjustments.money.format(symbol: false)] } + .join('" + \'\x0A\' + "')}", + '\x0A', + "#{checkout_adjustments_for(@order, exclude: [:line_item]) + .reject{ |a| a.amount == 0 } + .reverse.map { |adjustment| '%5s %-27.27s%8.8s' % + ["", + raw(adjustment.label), + display_adjustment_amount(adjustment).money.format(symbol: false)] } + .join('" + \'\x0A\' + "')}", + '\x0A', + '__________________________________________' + '\x0A', + '\x0A', + '\x1B' + '\x45' + '\x0D', // bold on + "#{'%31s%10s' % + [t(:total_incl_tax), + @order.display_total]}", + '\x1B' + '\x45' + '\x0A', // bold off + '\x0A', + "#{display_checkout_taxes_hash(@order).map { |tax_rate, tax_value| + '%31s%10s' % + [t(:tax_total, rate: tax_rate), + tax_value] } + .join('" + \'\x0A\' + "')}", + '\x0A', + "#{'%31s%10s' % + [t(:total_excl_tax), + display_checkout_total_less_tax(@order)]}", + '\x0A', + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A' + '\x0A', + '\x1B' + '\x69', // cut paper + ]; + = javascript_include_tag "qz/ticket-popup.js" + %body + %div#printer-list + + diff --git a/app/views/spree/admin/products/bulk_edit/_header.html.haml b/app/views/spree/admin/products/bulk_edit/_header.html.haml index 09586b3e7c..8284ada662 100644 --- a/app/views/spree/admin/products/bulk_edit/_header.html.haml +++ b/app/views/spree/admin/products/bulk_edit/_header.html.haml @@ -1,5 +1,5 @@ - content_for :page_title do - = "Bulk Edit Products" + = t('.title') - content_for :page_actions do %div{ :class => "toolbar", 'data-hook' => "toolbar" } diff --git a/app/views/spree/admin/products/bulk_edit/_indicators.html.haml b/app/views/spree/admin/products/bulk_edit/_indicators.html.haml index 4760dacaeb..bfdd104690 100644 --- a/app/views/spree/admin/products/bulk_edit/_indicators.html.haml +++ b/app/views/spree/admin/products/bulk_edit/_indicators.html.haml @@ -3,14 +3,14 @@ %div.sixteen.columns.alpha#loading{ 'ng-if' => 'loading' } %img.spinner{ src: "/assets/spinning-circles.svg" } - %h1 LOADING PRODUCTS + %h1= t('.title') %div.sixteen.columns.alpha{ 'ng-show' => '!loading && filteredProducts.length == 0 && query.length==0' } - %h1#no_results No products yet. Why don't you add some? + %h1#no_results= t('.no_products') %div.sixteen.columns.alpha{ 'ng-show' => '!loading && filteredProducts.length == 0 && query.length!=0' } - %h1#no_results - Sorry, no results match + %h1#no_results + = t('.no_results') ' {{query}} ' \ No newline at end of file diff --git a/app/views/spree/admin/reports/_sales_tax_description.html.haml b/app/views/spree/admin/reports/_sales_tax_description.html.haml new file mode 100644 index 0000000000..5f4f7f6dfd --- /dev/null +++ b/app/views/spree/admin/reports/_sales_tax_description.html.haml @@ -0,0 +1,4 @@ +%ul{style: "margin-left: 12pt"} + - report_types.each do |report_type| + %li + = link_to report_type[0], "#{sales_tax_admin_reports_url}?report_type=#{report_type[1]}" diff --git a/app/views/spree/admin/reports/sales_tax.html.haml b/app/views/spree/admin/reports/sales_tax.html.haml index 9a5cb9e533..c90603d001 100644 --- a/app/views/spree/admin/reports/sales_tax.html.haml +++ b/app/views/spree/admin/reports/sales_tax.html.haml @@ -5,9 +5,15 @@ .four.columns.alpha = label_tag nil, t(:report_distributor) = f.collection_select(:distributor_id_eq, @distributors, :id, :name, {:include_blank => 'All'}, {:class => "select2 fullwidth"}) + = label_tag nil, t(:report_customers_type) + %br + = select_tag(:report_type, options_for_select([[t(:report_tax_types),:tax_types],[t(:report_tax_rates),:tax_rates]], @report_type)) + %br + %br = check_box_tag :csv = label_tag :csv, t(:report_customers_csv) %br + %br = button t(:search) %br diff --git a/app/views/spree/admin/variants/_autocomplete.js.erb b/app/views/spree/admin/variants/_autocomplete.js.erb index 41b0e84550..ccd93d63f7 100644 --- a/app/views/spree/admin/variants/_autocomplete.js.erb +++ b/app/views/spree/admin/variants/_autocomplete.js.erb @@ -9,11 +9,10 @@
-
{{variant.name}}
{{/if}} -
diff --git a/app/views/spree/order_mailer/invoice_email.html.haml b/app/views/spree/order_mailer/invoice_email.html.haml index e2a2aa8967..4c2b8b73b6 100644 --- a/app/views/spree/order_mailer/invoice_email.html.haml +++ b/app/views/spree/order_mailer/invoice_email.html.haml @@ -2,9 +2,9 @@ %tr %td %h3 - Hi #{@order.bill_address.firstname}, + = t('.hi', name: @order.bill_address.firstname) %h4 - Please find attached an invoice for your recent order from + = t('.invoice_attached_text') %strong= "#{@order.distributor.name}" = render 'signoff' diff --git a/config/environments/production.rb b/config/environments/production.rb index 819bb98306..73aceefed2 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -56,7 +56,7 @@ Openfoodnetwork::Application.configure do # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) - config.i18n.fallbacks = true + config.i18n.fallbacks = [:en] # Send deprecation notices to registered listeners config.active_support.deprecation = :notify diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index 5542c29963..2269ed6d92 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -39,16 +39,12 @@ en-GB: must_have_valid_business_number: "Please enter your company number." invoice: "Invoice" percentage_of_sales: "%{percentage} of sales" - percentage_of_turnover: "Percentage of turnover" - monthly_cap_excl_tax: "monthly cap (excl. VAT)" capped_at_cap: "capped at %{cap}" per_month: "per month" free: "pay what you can" free_trial: "free trial" plus_tax: "plus VAT" - total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. VAT)" min_bill_turnover_desc: "once turnover exceeds %{mbt_amount}" - business_model_configuration: "Business model configuration" say_no: "No" say_yes: "Yes" then: then @@ -82,6 +78,51 @@ en-GB: has_one_rule: "has one rule" has_n_rules: "has %{num} rules" unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Accounts & Billing" + accounts_administration_distributor: "Accounts Administration Distributor" + admin_settings: "Settings" + update_invoice: "Update Invoices" + finalise_invoice: "Finalise Invoices" + finalise_user_invoices: "Finalise User Invoices" + finalise_user_invoice_explained: "Use this button to finalise all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." + manually_run_task: "Manually Run Task" + update_user_invoices: "Update User Invoices" + update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." + auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" + auto_update_invoices: "Auto-update invoices nightly at 1:00am" + business_model_configuration: + edit: + business_model_configuration: "Business Model" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Shop Trial Length (Days)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Percentage of turnover" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "monthly cap (excl. VAT)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Include Tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. VAT)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Add Customer" @@ -597,7 +638,6 @@ en-GB: products_max_quantity: Max quantity products_distributor: Distributor products_distributor_info: When you select a distributor for your order, their address and pickup times will be displayed here. - shop_trial_length: "Shop Trial Length (Days)" shop_trial_expires_in: "Your shopfront trial expires in" shop_trial_expired_notice: "OFN UK is a non-profit social enterprise making software affordable through open source collaboration. Thanks for being part of it!" password: Password @@ -826,16 +866,6 @@ en-GB: roles: "Roles" update: "Update" add_producer_property: "Add producer property" - admin_settings: "Settings" - update_invoice: "Update Invoices" - finalise_invoice: "Finalise Invoices" - finalise_user_invoices: "Finalise User Invoices" - finalise_user_invoice_explained: "Use this button to finalise all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." - manually_run_task: "Manually Run Task" - update_user_invoices: "Update User Invoices" - update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." - auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" - auto_update_invoices: "Auto-update invoices nightly at 1:00am" in_progress: "In Progress" started_at: "Started at" queued: "Queued" @@ -846,8 +876,6 @@ en-GB: no_customers_found: "No customers found" go: "Go" hub: "Hub" - accounts_administration_distributor: "accounts administration distributor" - accounts_and_billing: "Accounts & Billing" producer: "Producer" product: "Product" price: "Price" @@ -895,6 +923,12 @@ en-GB: edit_profile_details_etc: "Change your profile description, images, etc." order_cycle: "Order Cycle" remove_tax: "Remove tax" + enterprise_terms_of_service: "Enterprise Terms of Service" + enterprises_require_tos: "Enterprises must accept Terms of Service" + enterprise_tos_link: "Enterprise Terms of Service link" + enterprise_tos_message: "We want to work with people that share our aims and values. As such we ask new enterprises to agree to our " + enterprise_tos_link_text: "Terms of Service." + enterprise_tos_agree: "I agree to the above Terms of Service" tax_settings: "Tax Settings" products_require_tax_category: "products require tax category" admin_shared_address_1: "Address" diff --git a/config/locales/en-US.yml b/config/locales/en-US.yml index f7e4b29abf..4a53382d00 100644 --- a/config/locales/en-US.yml +++ b/config/locales/en-US.yml @@ -53,13 +53,10 @@ en-US: must_have_valid_business_number: "%{enterprise_name} must have a valid ABN before invoices can be sent." invoice: "Invoice" percentage_of_sales: "%{percentage} of sales" - percentage_of_turnover: "Percentage of turnover" - monthly_cap_excl_tax: "monthly cap (excl. GST)" capped_at_cap: "capped at %{cap}" per_month: "per month" free: "free" plus_tax: "plus GST" - total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)" say_no: "No" say_yes: "Yes" @@ -84,7 +81,51 @@ en-US: tag_has_rules: "Existing rules for this tag: %{num}" has_one_rule: "has one rule" has_n_rules: "has %{num} rules" - + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Accounts & Billing" + accounts_administration_distributor: "Accounts Administration Distributor" + admin_settings: "Settings" + update_invoice: "Update Invoices" + finalise_invoice: "Finalise Invoices" + finalise_user_invoices: "Finalise User Invoices" + finalise_user_invoice_explained: "Use this button to finalize all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." + manually_run_task: "Manually Run Task " + update_user_invoices: "Update User Invoices" + update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." + auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" + auto_update_invoices: "Auto-update invoices nightly at 1:00am" + business_model_configuration: + edit: + business_model_configuration: "Business Model" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Shop Trial Length (Days)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Percentage of turnover" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "monthly cap (excl. GST)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Include Tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Add customer" @@ -858,16 +899,6 @@ Please follow the instructions there to make your enterprise visible on the Open roles: "Roles" update: "Update" add_producer_property: "Add producer property" - admin_settings: "Settings" - update_invoice: "Update Invoices" - finalise_invoice: "Finalise Invoices" - finalise_user_invoices: "Finalise User Invoices" - finalise_user_invoice_explained: "Use this button to finalize all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." - manually_run_task: "Manually Run Task " - update_user_invoices: "Update User Invoices" - update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." - auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" - auto_update_invoices: "Auto-update invoices nightly at 1:00am" in_progress: "In Progress" started_at: "Started at" queued: "Queued" @@ -878,8 +909,6 @@ Please follow the instructions there to make your enterprise visible on the Open no_customers_found: "No customers found" go: "Go" hub: "Hub" - accounts_administration_distributor: "accounts administration distributor" - accounts_and_billing: "Accounts & Billing" producer: "Producer" product: "Product" price: "Price" @@ -1015,7 +1044,7 @@ Please follow the instructions there to make your enterprise visible on the Open validation_msg_product_category_cant_be_blank: "^Product Category cant be blank" validation_msg_tax_category_cant_be_blank: "^Tax Category can't be blank" validation_msg_is_associated_with_an_exising_customer: "is associated with an existing customer" - + spree: shipment_states: backorder: backorder diff --git a/config/locales/en.yml b/config/locales/en.yml index 9590047ba2..475942a692 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -46,6 +46,8 @@ en: producers_join: Australian producers are now welcome to join the Open Food Network. #FIXME charges_sales_tax: Charges GST? print_invoice: "Print Invoice" + print_ticket: "Print Ticket" + select_ticket_printer: "Select printer for tickets" send_invoice: "Send Invoice" resend_confirmation: "Resend Confirmation" view_order: "View Order" @@ -57,16 +59,12 @@ en: must_have_valid_business_number: "%{enterprise_name} must have a valid ABN before invoices can be sent." invoice: "Invoice" percentage_of_sales: "%{percentage} of sales" - percentage_of_turnover: "Percentage of turnover" - monthly_cap_excl_tax: "monthly cap (excl. GST)" capped_at_cap: "capped at %{cap}" per_month: "per month" free: "free" free_trial: "free trial" plus_tax: "plus GST" - total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)" min_bill_turnover_desc: "once turnover exceeds %{mbt_amount}" - business_model_configuration: "Business model configuration" say_no: "No" say_yes: "Yes" then: then @@ -80,6 +78,7 @@ en: loading: Loading... show_more: Show more show_all: Show all + show_all_with_more: "Show All (%{num} More)" cancel: Cancel admin: @@ -120,6 +119,53 @@ en: unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?" unsaved_changes: "You have unsaved changes" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Accounts & Billing" + accounts_administration_distributor: "Accounts Administration Distributor" + admin_settings: "Settings" + update_invoice: "Update Invoices" + auto_update_invoices: "Auto-update invoices nightly at 1:00am" + finalise_invoice: "Finalise Invoices" + auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" + manually_run_task: "Manually Run Task " + update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." + finalise_user_invoices: "Finalise User Invoices" + finalise_user_invoice_explained: "Use this button to finalize all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." + update_user_invoices: "Update User Invoices" + + business_model_configuration: + edit: + business_model_configuration: "Business Model" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Shop Trial Length (Days)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Percentage of turnover" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "monthly cap (excl. GST)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total Monthly Bill (Incl. Tax)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." + customers: index: add_customer: "Add Customer" @@ -144,6 +190,7 @@ en: cache_settings: show: + title: Caching distributor: Distributor order_cycle: Order Cycle status: Status @@ -274,10 +321,11 @@ en: inventory_settings: text1: You may opt to manage stock levels and prices in via your inventory: inventory - text2: "If you are using the inventory tool, you can select whether new products \ - added by your suppliers need to be added to your inventory before they can be \ - stocked. If you are not using your inventory to manage your products you should \ - select the 'recommended' option below:" + text2: > + If you are using the inventory tool, you can select whether new products + added by your suppliers need to be added to your inventory before they can be + stocked. If you are not using your inventory to manage your products you should + select the 'recommended' option below: preferred_product_selection_from_inventory_only_yes: New products can be put into my shopfront (recommended) preferred_product_selection_from_inventory_only_no: New products must be added to my inventory before they can be put into my shopfront payment_methods: @@ -306,7 +354,7 @@ en: visible: Visible not_visible: Not visible permalink: Permalink (no spaces) - permalink_tip: "This permalink is used to create the url to your shop: {{link}} your-shop-name/shop" + permalink_tip: "This permalink is used to create the url to your shop: %{link}your-shop-name/shop" link_to_front: Link to shop front link_to_front_tip: A direct link to your shopfront on the Open Food Network. shipping_methods: @@ -325,12 +373,12 @@ en: allow_guest_orders_tip: "Allow checkout as guest or require a registered user." allow_guest_orders_false: "Require login to order" allow_guest_orders_true: "Allow guest checkout" - shopfront_message_placeholder: \ - An optional explanation for customers detailing how your shopfront works, \ + shopfront_message_placeholder: > + An optional explanation for customers detailing how your shopfront works, to be displayed above the product list on your shop page. - shopfront_closed_message_placeholder: \ - A message which provides a more detailed explanation about why your shop is \ - closed and/or when customers can expect it to open again. This is displayed \ + shopfront_closed_message_placeholder: > + A message which provides a more detailed explanation about why your shop is + closed and/or when customers can expect it to open again. This is displayed on your shop only when you have no active order cycles (ie. shop is closed). open_date: Open Date close_date: Close Date @@ -394,6 +442,8 @@ en: choose_option: Please choose one of the options above. change_now: Change now enterprise_user_index: + loading_enterprises: LOADING ENTERPRISES + no_enterprises_found: No enterprises found. search_placeholder: Search By Name manage: Manage new_form: @@ -415,7 +465,7 @@ en: order_cycles: advanced_settings: title: Advanced Settings - choose_product_tip: You can opt to restrict all available products (both incoming and outgoing), to only those in {{inventory}}'s inventory. + choose_product_tip: You can opt to restrict all available products (both incoming and outgoing), to only those in %{inventory}'s inventory. preferred_product_selection_from_coordinator_inventory_only_here: Coordinator's Inventory Only preferred_product_selection_from_coordinator_inventory_only_all: All Available Products save_reload: Save and Reload Page @@ -461,6 +511,11 @@ en: shared: user_guide_link: user_guide: User Guide + invoice_settings: + edit: + title: Invoice Settings + invoice_style2?: Use the alternative invoice model that includes total tax breakdown per rate and tax rate info per item (not yet suitable for countries displaying prices excluding tax) + enable_receipt_printing?: Show options for printing receipts using thermal printers in order dropdown? home: hubs: @@ -481,10 +536,30 @@ en: require_customer_html: "Please %{contact} %{enterprise} to become a customer." # Printable Invoice Columns - invoice_column_item: "Item" - invoice_column_qty: "Qty" + invoice_billing_address: "Billing address:" invoice_column_tax: "GST" invoice_column_price: "Price" + invoice_column_item: "Item" + invoice_column_qty: "Qty" + invoice_column_unit_price_with_taxes: "Unit price (Incl. tax)" + invoice_column_unit_price_without_taxes: "Unit price (Excl. tax)" + invoice_column_price_with_taxes: "Total price (Incl. tax)" + invoice_column_price_without_taxes: "Total price (Excl. tax)" + invoice_column_tax_rate: "Tax rate" + tax_invoice: "TAX INVOICE" + tax_total: "Total tax (%{rate}):" + total_excl_tax: "Total (Excl. tax):" + total_incl_tax: "Total (Incl. tax):" + abn: "ABN:" + acn: "ACN:" + invoice_issued_on: "Invoice issued on:" + order_number: "Invoice number:" + date_of_transaction: "Date of transaction:" + + ticket_column_qty: "Qty" + ticket_column_item: "Item" + ticket_column_unit_price: "Unit Price" + ticket_column_total_price: "Total Price" logo: "Logo (640x130)" #FIXME logo_mobile: "Mobile logo (75x26)" #FIXME @@ -949,7 +1024,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using products_distributor: Distributor products_distributor_info: When you select a distributor for your order, their address and pickup times will be displayed here. - shop_trial_length: "Shop Trial Length (Days)" shop_trial_expires_in: "Your shopfront trial expires in" shop_trial_expired_notice: "Good news! We have decided to extend shopfront trials until further notice." @@ -1187,16 +1261,6 @@ Please follow the instructions there to make your enterprise visible on the Open roles: "Roles" update: "Update" add_producer_property: "Add producer property" - admin_settings: "Settings" - update_invoice: "Update Invoices" - finalise_invoice: "Finalise Invoices" - finalise_user_invoices: "Finalise User Invoices" - finalise_user_invoice_explained: "Use this button to finalize all invoices in the system for the previous calendar month. This task can be set up to run automatically once a month." - manually_run_task: "Manually Run Task " - update_user_invoices: "Update User Invoices" - update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." - auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" - auto_update_invoices: "Auto-update invoices nightly at 1:00am" in_progress: "In Progress" started_at: "Started at" queued: "Queued" @@ -1207,8 +1271,6 @@ Please follow the instructions there to make your enterprise visible on the Open no_customers_found: "No customers found" go: "Go" hub: "Hub" - accounts_administration_distributor: "accounts administration distributor" - accounts_and_billing: "Accounts & Billing" producer: "Producer" product: "Product" price: "Price" @@ -1257,6 +1319,12 @@ Please follow the instructions there to make your enterprise visible on the Open edit_profile_details_etc: "Change your profile description, images, etc." order_cycle: "Order Cycle" remove_tax: "Remove tax" + enterprise_terms_of_service: "Enterprise Terms of Service" + enterprises_require_tos: "Enterprises must accept Terms of Service" + enterprise_tos_link: "Enterprise Terms of Service link" + enterprise_tos_message: "We want to work with people that share our aims and values. As such we ask new enterprises to agree to our " + enterprise_tos_link_text: "Terms of Service." + enterprise_tos_agree: "I agree to the above Terms of Service" tax_settings: "Tax Settings" products_require_tax_category: "products require tax category" admin_shared_address_1: "Address" @@ -1290,6 +1358,22 @@ Please follow the instructions there to make your enterprise visible on the Open report_order_cycle: "Order Cycle: " report_entreprises: "Enterprises: " report_users: "Users: " + report_tax_rates: "Tax rates" + report_tax_types: "Tax types" + report_header_order_number: "Order number" + report_header_date: "Date" + report_header_items: "Items" + report_header_items_total: "Items total %{currency_symbol}" + report_header_taxable_items_total: "Taxable Items Total (%{currency_symbol})" + report_header_sales_tax: "Sales Tax (%{currency_symbol})" + report_header_delivery_charge: "Delivery Charge (%{currency_symbol})" + report_header_tax_on_delivery: "Tax on Delivery (%{currency_symbol})" + report_header_tax_on_fees: "Tax on Fees (%{currency_symbol})" + report_header_total_tax: "Total Tax (%{currency_symbol})" + report_header_customer: "Customer" + report_header_distributor: "Distributor" + report_header_total_excl_vat: "Total excl. tax (%{currency_symbol})" + report_header_total_incl_vat: "Total incl. tax (%{currency_symbol})" initial_invoice_number: "Initial invoice number:" invoice_date: "Invoice date:" due_date: "Due date:" @@ -1334,7 +1418,137 @@ Please follow the instructions there to make your enterprise visible on the Open validation_msg_tax_category_cant_be_blank: "^Tax Category can't be blank" validation_msg_is_associated_with_an_exising_customer: "is associated with an existing customer" + js: + admin: + modals: + got_it: Got it + tag_rule_help: + title: Tag Rules + overview: Overview + overview_text: > + Tag rules provide a way to describe which items are visible or otherwise + to which customers. Items can be Shipping Methods, Payment Methods, + Products and Order Cycles. + by_default_rules: "'By Default...' Rules" + by_default_rules_text: > + Default rules allow you to hide items so that they are not visible by default. + This behaviour can then be overriden by non-default rules for customers with + particular tags. + customer_tagged_rules: "'Customers Tagged...' Rules" + customer_tagged_rules_text: > + By creating rules related to a specific customer tag, you can override the default + behaviour (whether it be to show or to hide items) for customers with the specified tag. + panels: + save: SAVE + saved: SAVED + saving: SAVING + enterprise_package: + hub_profile: Hub Profile + hub_profile_cost: "COST: ALWAYS FREE" + hub_profile_text1: > + People can find and contact you on the Open Food Network. Your enterprise will be + visible on the map, and will be searchable in listings. + hub_profile_text2: > + Having a profile, and making connections within your local food system through + the Open Food Network will always be free. + hub_shop: Hub Shop + hub_shop_text1: > + Your enterprise is the backbone of your local food system. You aggregate produce + from other enterprises and can sell it through your shop on the Open Food Network. + hub_shop_text2: > + Hubs can take many forms, whether they be a food co-op, a buying group, a veggie-box + program, or a local grocery store. + hub_shop_text3: > + If you also want to sell your own products, you will need to switch this enterprise + to be a producer. + choose_package: Please Choose a Package + choose_package_text1: > + Your enterprise will not be fully activated until a package is selected from the + options on the left. + choose_package_text2: > + Click on an option to see more detailed information about each package, and hit + the red SAVE button when you are done! + profile_only: Profile Only + profile_only_cost: "COST: ALWAYS FREE" + profile_only_text1: > + A profile makes you visible and contactable to others and is a way to share your story. + profile_only_text2: > + If you prefer to focus on producing food, and want to leave the work of selling it + to someone else, you won't require a shop on the Open Food Network. + profile_only_text3: > + Add your products to Open Food Network, allowing hubs to stock your products in + their stores. + producer_shop: Producer Shop + producer_shop_text1: > + Sell your products directly to customers through your very own Open Food Network + shopfront. + producer_shop_text2: > + A Producer Shop is for your produce only, if you want to sell produce grown/produced + off site, please select 'Producer Hub'. + producer_hub: Producer Hub + producer_hub_text1: > + Your enterprise is the backbone of your local food system. You can sell your own + produce as well as produce aggregated from other enterprises through your shopfront + on the Open Food Network. + producer_hub_text2: > + Producer Hubs can take many forms, whether they be a CSA, a veggie-box program, + or a food co-op with a rooftop garden. + producer_hub_text3: > + The Open Food Network aims to support as many hub models as possible, so no matter + your situation, we want to provide the tools you need to run your organisation or + local food business. + get_listing: Get a listing + always_free: ALWAYS FREE + sell_produce_others: Sell produce from others + sell_own_produce: Sell your own produce + sell_both: Sell produce from self and others + enterprise_producer: + producer: Producer + producer_text1: > + Producers make yummy things to eat or drink. You're a producer if you grow it, + raise it, brew it, bake it, ferment it, milk it or mould it. + producer_text2: > + Producers can also perform other functions, such as aggregating food from other + enterprises and selling it through a shop on the Open Food Network. + non_producer: Non-producer + non_producer_text1: > + Non-producers do not produce any food themselves, meaning that they cannot create + their own products for sale through the Open Food Network. + non_producer_text2: > + Instead, non-producers specialise in linking producers to the end eater, whether it + be by aggregating, grading, packing, selling or delivering food. + producer_desc: Producers of food + producer_example: eg. GROWERS, BAKERS, BREWERS, MAKERS + non_producer_desc: All other food enterprises + non_producer_example: eg. Grocery stores, Food co-ops, Buying groups + enterprise_status: + status_title: "%{name} is set up and ready to go!" + severity: Severity + description: Description + resolve: Resolve + new_tag_rule_dialog: + select_rule_type: "Select a rule type:" + out_of_stock: + reduced_stock_available: Reduced stock available + out_of_stock_text: > + While you've been shopping, the stock levels for one or more of the products + in your cart have reduced. Here's what's changed: + now_out_of_stock: is now out of stock. + only_n_remainging: "now only has %{num} remaining." + spree: + admin: + products: + bulk_edit: + header: + title: Bulk Edit Products + indicators: + title: LOADING PRODUCTS + no_products: "No products yet. Why don't you add some?" + no_results: "Sorry, no results match" + variants: + autocomplete: + producer_name: Producer date_picker: format: ! '%Y-%m-%d' js_format: 'yy-mm-dd' @@ -1356,6 +1570,10 @@ Please follow the instructions there to make your enterprise visible on the Open processing: processing void: void invalid: invalid + order_mailer: + invoice_email: + hi: "Hi %{name}" + invoice_attached_text: Please find attached an invoice for your recent order from order_state: address: address adjustments: adjustments @@ -1369,3 +1587,6 @@ Please follow the instructions there to make your enterprise visible on the Open resumed: resumed returned: returned skrill: skrill + orders: + invoice: + tax_invoice: "TAX INVOICE: " diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 5daa830beb..695a8c468c 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -28,6 +28,8 @@ fr: producers_join: Les producteurs et autres hubs basés en France sont invités à rejoindre Open Food France. charges_sales_tax: Soumis à la TVA? print_invoice: "Imprimer la facture" + print_ticket: "Imprimer le ticket" + select_ticket_printer: "Choisir l'imprimante à tickets" send_invoice: "Envoyer la facture" resend_confirmation: "Renvoyer la confirmation" view_order: "Voir la commande" @@ -39,16 +41,12 @@ fr: must_have_valid_business_number: "%{enterprise_name} doit avoir un SIRET valide avant que les factures puissent être envoyées." invoice: "Facture" percentage_of_sales: "%{percentage} des ventes" - percentage_of_turnover: "Pourcentage du chiffre d'affaire" - monthly_cap_excl_tax: "plafond mensuel (sans TVA)" capped_at_cap: "plafonné à %{cap}" per_month: "par mois" free: "gratuit" free_trial: "Utilisation contre contribution libre" plus_tax: "plus TVA" - total_monthly_bill_incl_tax: "Facture mensuelle totale (taxes incluses)" min_bill_turnover_desc: "Quand le chiffre d'affaire dépasse %{mbt_amount}" - business_model_configuration: "Configuration du modèle économique" say_no: "Non" say_yes: "Oui" then: puis @@ -93,6 +91,51 @@ fr: has_n_rules: "a %{num} règles" unsaved_confirm_leave: "Des modifications n'ont pas été sauvegardées et seront perdues si vous quittez la page. Souhaitez-vous quitter la page?" unsaved_changes: "Des modifications n'ont pas été sauvegardées." + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Compte & Facturation" + accounts_administration_distributor: "entreprise d'administration des comptes (facturation des hubs)" + admin_settings: "Paramètres" + update_invoice: "Mettre à jour les factures" + finalise_invoice: "Finaliser les factures" + finalise_user_invoices: "Finaliser les factures utilisateurs" + finalise_user_invoice_explained: "Cliquez ici pour finaliser toutes les factures pour le mois calendaire précédent. Cette tâche peut-être définie pour être opérée automatiquement une fois par mois." + manually_run_task: "Tache manuelle" + update_user_invoices: "Mettre à jour les factures utilisateurs" + update_user_invoice_explained: "Cliquez ici pour mettre à jour immédiatement les factures pour le mois en cours pour toutes les entreprises utilisant le système. Cette tache peut être définie pour s'effectuer automatiquement chaque nuit." + auto_finalise_invoices: "Finaliser automatiquement les factures le 2 de chaque mois à 01:30" + auto_update_invoices: "Mettre à jour automatiquement les factures chaque nuit à 01:00" + business_model_configuration: + edit: + business_model_configuration: "Configuration du modèle économique" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Durée de la période de test (jours)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Pourcentage du chiffre d'affaire" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "plafond mensuel (sans TVA)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Facture mensuelle totale (taxes incluses)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Ajouter un acheteur" @@ -232,8 +275,8 @@ fr: promo_image_note2: Votre bannière doit mesurer 1200 x 260, toute image non conforme sera rognée. promo_image_note3: La bannière est affichée en haut de la page de votre entreprise et dans sa version condensée (pop-up). inventory_settings: - text1: Vous pouvez choisir de gérer vos stocks et prix via votre - inventory: catalogue boutique + text1: Vous pouvez gérer votre stock et vos prix via votre + inventory: inventaire text2: "Si vous utilisez l'outil \"catalogue boutique\", vous pouvez choisir si les nouveaux produits ajoutés par vos fournisseurs à leurs catalogues doivent être ajoutés à votre catalogue boutique avant de pouvoir être mis en ligne dans votre boutique. Si vous n'utilisez pas l'outil \"catalogue boutique\", sélectionnez l'option précisant \"recommandé\" ci-dessous:" preferred_product_selection_from_inventory_only_yes: Les nouveaux produits des producteurs peuvent être ajoutés à ma boutique en ligne (recommandé) preferred_product_selection_from_inventory_only_no: Les nouveaux produits des producteurs doivent être ajoutés à mon catalogue boutique avant de pouvoir être ajoutés à ma boutique en ligne @@ -261,11 +304,11 @@ fr: visible_in_search: Apparaît sur la plateforme? visible_in_search_tip: Indiquez si vous souhaitez ou ne souhaitez pas que votre entreprise apparaisse sur la carte et dans la liste des boutiques. visible: Visible - not_visible: Invisible - permalink: Nom affiché dans l'URL (sans espace) - permalink_tip: "Ce nom sera utilisé pour créer le lien url permanent de votre boutique {{link}} votre-boutique/shop" - link_to_front: Lien URL de la boutique - link_to_front_tip: C'est le lien qui permet d'accéder en direct à votre boutique sur Open Food France. + not_visible: Pas visible + permalink: Lien (pas d'espace) + permalink_tip: "This permalink is used to create the url to your shop: %{link}your-shop-name/shop" + link_to_front: Link to shop front + link_to_front_tip: A direct link to your shopfront on the Open Food Network. shipping_methods: name: Nom applies: Active? @@ -274,10 +317,10 @@ fr: create_one_button: Créer une commission no_method_yet: Vous n'avez pas encore paramétré de méthode de livraison. shop_preferences: - shopfront_requires_login: "Boutique visible par tous?" - shopfront_requires_login_tip: "Choisissez si les acheteurs doivent être connectés pour voir la boutique ou si la boutique est visible par tout le monde." + shopfront_requires_login: "Cette boutique exige un login?" + shopfront_requires_login_tip: "Les acheteurs doivent-ils se connecter pour accéder à la boutique?" shopfront_requires_login_false: "Visible par tous" - shopfront_requires_login_true: "Visible uniquement pour les acheteurs logués" + shopfront_requires_login_true: "Demander aux acheteurs de se connecter" allow_guest_orders: "Commandes des invités" allow_guest_orders_tip: "Autoriser la commande en tant qu'invité ou demander que l'acheteur soit logué." allow_guest_orders_false: "Demander que l'acheteur se logue pour pouvoir commander" @@ -367,7 +410,7 @@ fr: order_cycles: advanced_settings: title: Paramétrages avancés - choose_product_tip: Vous pouvez choisir de restreindre la liste des produits pouvant être proposés dans votre cycle de vente (produits entrants et sortants) aux produits du catalogue producteur de l'entreprise {{inventory}}. + choose_product_tip: Vous pouvez choisir de restreindre la liste des produits pouvant être proposés dans votre cycle de vente (produits entrants et sortants) aux produits du catalogue producteur de l'entreprise %{inventory}. preferred_product_selection_from_coordinator_inventory_only_here: Uniquement les produits du catalogue boutique preferred_product_selection_from_coordinator_inventory_only_all: Tous les produits disponibles dans les catalogues producteurs save_reload: Sauvegarder et rafraichir la page @@ -411,7 +454,12 @@ fr: title: Propriétés / labels du producteur shared: user_guide_link: - user_guide: Guide utilisateur + user_guide: Guide l'utilisateur + invoice_settings: + edit: + title: Apparence de la facture + invoice_style2?: Utiliser le modèle de facture alternaltif qui comprend une séparation des taxes par taux et une indication du taux appliqué par item (pas encore adapté pour les pays affichant des prix hors taxe) + home: hubs: show_closed_shops: "Aficher les boutiques fermées" @@ -427,12 +475,39 @@ fr: register: "s'inscrire" contact: "contact" require_customer_login: "La boutique est réservée aux membres." - require_login_html: "Déjà inscrit? %{Connectez-vous}. Sinon, %{inscrivez-vous} pour pouvoir faire vos achats." - require_customer_html: "Veuillez %{contacter} %{l'entreprise} pour devenir membre." + require_login_html: "Déjà inscrit? %{login}. Sinon, %{register} pour pouvoir faire vos achats." + require_customer_html: "Veuillez %{contact} %{enterprise} pour devenir membre." + + invoice_billing_address: "Adresse de facturation :" + invoice_column_tax: "TVA" + invoice_column_price: "Prix" invoice_column_item: "Produit" invoice_column_qty: "Qté" invoice_column_tax: "TVA" invoice_column_price: "Prix" + invoice_column_unit_price_with_taxes: "Prix unitaire (TTC)" + invoice_column_unit_price_without_taxes: "Prix unitaire (HT)" + invoice_column_price_with_taxes: "Prix total (TTC)" + invoice_column_price_without_taxes: "Prix total (HT)" + invoice_column_tax_rate: "Taux TVA" + tax_invoice: "FACTURE" + tax_total: "Total TVA (%{rate}) :" + total_excl_tax: "Total HT :" + total_incl_tax: "Total TTC :" + abn: "SIRET :" + acn: "n° TVA :" + invoice_issued_on: "Facture éditée le :" + order_number: "Numéro de facture :" + date_of_transaction: "Date de la transaction :" + number: + percentage: + format: + format: "%n %" + ticket_column_qty: "Qté" + ticket_column_item: "Item" + ticket_column_unit_price: "Px Unit" + ticket_column_total_price: "Px Total" + logo: "Logo (640x130)" logo_mobile: "Logo smartphone (75x26)" logo_mobile_svg: "Logo smartphone (SVG)" @@ -583,7 +658,7 @@ fr: order_paid: RÉGLÉ order_not_paid: NON RÉGLÉ order_total: Total commande - order_payment: "Payer via:" + order_payment: "Paiement par :" order_billing_address: Adresse de facturation order_delivery_on: Livraison prévue order_delivery_address: Adresse de livraison @@ -636,7 +711,7 @@ fr: email_payment_paid: RÉGLÉ email_payment_not_paid: NON RÉGLÉ email_payment_summary: Résumé du paiement - email_payment_method: "Payer via :" + email_payment_method: "Moyen de paiement :" email_shipping_delivery_details: Détails de livraison email_shipping_delivery_time: "Livré le:" email_shipping_delivery_address: "Adresse de livraison:" @@ -838,7 +913,6 @@ fr: products_max_quantity: Quantité max products_distributor: Distributeur products_distributor_info: Quand vous choisissez un distributeur pour votre commande, les adresse et date de retrait seront affichées ici. - shop_trial_length: "Durée de la période de test (jours)" shop_trial_expires_in: "Votre période de test se termine dans" shop_trial_expired_notice: "Vous pouvez continuer à utiliser la plateforme en contrepartie d'une contribution libre et volontaire. Merci de nous informer de la façon dont vous souhaitez contribuer :-)" password: Mot de passe @@ -1067,16 +1141,6 @@ fr: roles: "Roles" update: "Mettre à jour" add_producer_property: "Ajouter une propriété" - admin_settings: "Paramètres" - update_invoice: "Mettre à jour les factures" - finalise_invoice: "Finaliser les factures" - finalise_user_invoices: "Finaliser les factures utilisateurs" - finalise_user_invoice_explained: "Cliquez ici pour finaliser toutes les factures pour le mois calendaire précédent. Cette tâche peut-être définie pour être opérée automatiquement une fois par mois." - manually_run_task: "Tache manuelle" - update_user_invoices: "Mettre à jour les factures utilisateurs" - update_user_invoice_explained: "Cliquez ici pour mettre à jour immédiatement les factures pour le mois en cours pour toutes les entreprises utilisant le système. Cette tache peut être définie pour s'effectuer automatiquement chaque nuit." - auto_finalise_invoices: "Finaliser automatiquement les factures le 2 de chaque mois à 01:30" - auto_update_invoices: "Mettre à jour automatiquement les factures chaque nuit à 01:00" in_progress: "En cours" started_at: "Commencé à" queued: "En attente" @@ -1087,8 +1151,6 @@ fr: no_customers_found: "Aucun acheteur trouvé" go: "Lancer" hub: "Hub" - accounts_administration_distributor: "entreprise d'administration des comptes (facturation des hubs)" - accounts_and_billing: "Compte & Facturation" producer: "Producteur" product: "Produit" price: "Prix" @@ -1169,6 +1231,22 @@ fr: report_order_cycle: "Cycle de vente:" report_entreprises: "Entreprises:" report_users: "Managers:" + report_tax_rates: "Taxes par taux" + report_tax_types: "Taxes par type" + report_header_order_number: "Numéro de commande" + report_header_date: "Date" + report_header_items: "Produits" + report_header_items_total: "Total des produits %{currency_symbol}" + report_header_taxable_items_total: "Total des produits taxés (%{currency_symbol})" + report_header_sales_tax: "Tax sur la vente (%{currency_symbol})" + report_header_delivery_charge: "Frais de livraison (%{currency_symbol})" + report_header_tax_on_delivery: "Taxe sur la livraison (%{currency_symbol})" + report_header_tax_on_fees: "Taxes sur les charges (%{currency_symbol})" + report_header_total_tax: "Taxe totale (%{currency_symbol})" + report_header_customer: "Acheteur" + report_header_distributor: "Distributeur" + report_header_total_excl_vat: "Total sans TVA (%{currency_symbol})" + report_header_total_incl_vat: "Total avec TVA (%{currency_symbol})" initial_invoice_number: "N° de facture initial:" invoice_date: "Date de facture:" due_date: "Date d'échéance:" diff --git a/config/locales/it.yml b/config/locales/it.yml index 646fd22229..9e7842c93e 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -39,16 +39,12 @@ it: must_have_valid_business_number: "%{enterprise_name} deve avere una partita iva valida per poter emettere fattura." invoice: "Fattura" percentage_of_sales: "%{percentage} di vendite" - percentage_of_turnover: "Percentuale di fatturato" - monthly_cap_excl_tax: "tetto mensile (IVA esclusa)" capped_at_cap: "limitato a %{cap}" per_month: "al mese" free: "gratuito" free_trial: "Prova gratuita" plus_tax: "più IVA" - total_monthly_bill_incl_tax: "Conto totale mensile (tasse incluse)" min_bill_turnover_desc: "dopo the il ricambio ha superato il %{mbt_amount}" - business_model_configuration: "Configurazione del modello di business" say_no: "No" say_yes: "Sì" then: poi @@ -81,6 +77,51 @@ it: tag_has_rules: "Regole esistenti per questo tag: %{num}" has_one_rule: "ha una regola" has_n_rules: "ha %{num} regole" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Account e conti" + accounts_administration_distributor: "account amministrazione distributore" + admin_settings: "Impostazioni" + update_invoice: "Aggiorna fattura" + finalise_invoice: "Finalizza le fatture" + finalise_user_invoices: "Finalizza le fatture dell'utente" + finalise_user_invoice_explained: "Usa questo bottone per finalizzare tutte le fatture nel sistema per il precedente mese. Questo processo può essere impostato per essere fatto automaticamente una volta al mese." + manually_run_task: "Elabora il processo manualmente" + update_user_invoices: "Aggiorna le fatture dell'utente" + update_user_invoice_explained: "Usa questo bottone per aggiornare a oggi immediatamente le fatture del mese per ogni impresa del sistema. Questo processo può essere impostato per essere eseguito automaticamente ogni notte." + auto_finalise_invoices: "Auto-finalizza le fatture il 2 di ogni mese alle 01:30" + auto_update_invoices: "Auto-aggiorna le fatture di notte alle 01:00" + business_model_configuration: + edit: + business_model_configuration: "Configurazione del modello di business" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Durata della prova per negozio (Giorni)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Percentuale di fatturato" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "tetto mensile (IVA esclusa)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Conto totale mensile (tasse incluse)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Aggiungi cliente" @@ -586,7 +627,6 @@ it: products_max_quantity: Quantità massima products_distributor: Distributore products_distributor_info: Quando selezioni un distributore per il tuo ordine, i suoi indirizzi e tempi di ritiro saranno mostrati qui. - shop_trial_length: "Durata della prova per negozio (Giorni)" shop_trial_expires_in: "La prova per la tua vetrina scadrà in" shop_trial_expired_notice: "Buone notizie! Abbiamo deciso di estendere le prove dei negozi fino a nuova notifica." password: Password @@ -815,16 +855,6 @@ it: roles: "Ruoli" update: "Aggiorna" add_producer_property: "Aggiungi proprietà produttori" - admin_settings: "Impostazioni" - update_invoice: "Aggiorna fattura" - finalise_invoice: "Finalizza le fatture" - finalise_user_invoices: "Finalizza le fatture dell'utente" - finalise_user_invoice_explained: "Usa questo bottone per finalizzare tutte le fatture nel sistema per il precedente mese. Questo processo può essere impostato per essere fatto automaticamente una volta al mese." - manually_run_task: "Elabora il processo manualmente" - update_user_invoices: "Aggiorna le fatture dell'utente" - update_user_invoice_explained: "Usa questo bottone per aggiornare a oggi immediatamente le fatture del mese per ogni impresa del sistema. Questo processo può essere impostato per essere eseguito automaticamente ogni notte." - auto_finalise_invoices: "Auto-finalizza le fatture il 2 di ogni mese alle 01:30" - auto_update_invoices: "Auto-aggiorna le fatture di notte alle 01:00" in_progress: "In elaborazione" started_at: "Iniziato alle" queued: "In coda" @@ -835,8 +865,6 @@ it: no_customers_found: "Nessun cliente trovato" go: "Vai" hub: "Distributore" - accounts_administration_distributor: "account amministrazione distributore" - accounts_and_billing: "Account e conti" producer: "Produttore" product: "Prodotto" price: "Prezzo" diff --git a/config/locales/nb.yml b/config/locales/nb.yml index fcd6482e61..04fa8f01f9 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -39,16 +39,12 @@ nb: must_have_valid_business_number: "%{enterprise_name} må ha et gyldig ORG nr. før fakturaer kan sendes." invoice: "Faktura" percentage_of_sales: "%{percentage} av handel" - percentage_of_turnover: "Prosent av omsetning" - monthly_cap_excl_tax: "månedlig tak (eks. MVA)" capped_at_cap: "tak på %{cap}" per_month: "pr. måned" free: "gratis" free_trial: "gratis prøveperiode" plus_tax: "pluss MVA" - total_monthly_bill_incl_tax: "Total månedlig regning (Inkl. Avgift)" min_bill_turnover_desc: "når omsettning overstiger %{mbt_amount}" - business_model_configuration: "Utforming av forretningsmodell" say_no: "Nei" say_yes: "Ja" then: vil @@ -81,6 +77,51 @@ nb: tag_has_rules: "Gjeldende regler for denne merkelappen: %{num}" has_one_rule: "har én regel" has_n_rules: "har %{num} regler" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Bokføring & Fakturering" + accounts_administration_distributor: "bokføringsadministrasjon distributør" + admin_settings: "Innstillinger" + update_invoice: "Oppdater Fakturaer" + finalise_invoice: "Sluttfør Fakturaer" + finalise_user_invoices: "Sluttfør Brukerfakturaer" + finalise_user_invoice_explained: "Bruk denne knappen til å sluttføre alle fakturaer i systemet for forrige kalendermåned. Denne oppgaven kan settes opp til å kjøres automatisk hver måned." + manually_run_task: "Gjør Oppgave Manuelt" + update_user_invoices: "Oppdater Brukerfakturaer" + update_user_invoice_explained: "Bruk denne knappen til umiddelbart å oppdatere fakturaer for måneden frem til i dag for hver bedriftsbruker i systemet. Denne oppgaven kan settes opp til å kjøres automatisk hver natt." + auto_finalise_invoices: "Auto-sluttfør fakturaer månedlig på den 2. kl. 01:30" + auto_update_invoices: "Auto-oppdater fakturaer hver natt kl. 01:00" + business_model_configuration: + edit: + business_model_configuration: "Utforming av forretningsmodell" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Lengden av prøveperioden (dager)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Prosent av omsetning" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "månedlig tak (eks. MVA)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total månedlig regning (Inkl. Avgift)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Legge til kunde" @@ -594,7 +635,6 @@ nb: products_max_quantity: Max mengde products_distributor: Distributør products_distributor_info: Når du velger en distributør for din bestilling, vil deres adresse og hentetider vises her. - shop_trial_length: "Lengden av prøveperioden (dager)" shop_trial_expires_in: "Din prøveperiode på butikkfront går ut om " shop_trial_expired_notice: "Gode nyheter! Vi har bestemt å forlenge butikkprøveperioder inntil ytterligere beskjed." password: Passord @@ -823,16 +863,6 @@ nb: roles: "Roller" update: "Oppdater" add_producer_property: "Legg til produsentegenskap" - admin_settings: "Innstillinger" - update_invoice: "Oppdater Fakturaer" - finalise_invoice: "Sluttfør Fakturaer" - finalise_user_invoices: "Sluttfør Brukerfakturaer" - finalise_user_invoice_explained: "Bruk denne knappen til å sluttføre alle fakturaer i systemet for forrige kalendermåned. Denne oppgaven kan settes opp til å kjøres automatisk hver måned." - manually_run_task: "Gjør Oppgave Manuelt" - update_user_invoices: "Oppdater Brukerfakturaer" - update_user_invoice_explained: "Bruk denne knappen til umiddelbart å oppdatere fakturaer for måneden frem til i dag for hver bedriftsbruker i systemet. Denne oppgaven kan settes opp til å kjøres automatisk hver natt." - auto_finalise_invoices: "Auto-sluttfør fakturaer månedlig på den 2. kl. 01:30" - auto_update_invoices: "Auto-oppdater fakturaer hver natt kl. 01:00" in_progress: "Pågår" started_at: "Startet" queued: "Satt i kø" @@ -843,8 +873,6 @@ nb: no_customers_found: "Fant ingen kunder" go: "Gå" hub: "Hub" - accounts_administration_distributor: "bokføringsadministrasjon distributør" - accounts_and_billing: "Bokføring & Fakturering" producer: "Produsent" product: "Produkt" price: "Pris" diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 80d83fdb3a..37a0c05dd4 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -37,16 +37,12 @@ pt-BR: confirm_resend_order_confirmation: "Tem certeza que deseja enviar novamente o pedido de confirmação do email?" invoice: "Fatura" percentage_of_sales: "%{percentage} de vendas" - percentage_of_turnover: " \"Percentual de faturamento\"" - monthly_cap_excl_tax: "limite mensal (taxas exclusas)" capped_at_cap: "limitado em %{cap}" per_month: "ao mês" free: "grátis" free_trial: "faça um teste grátis" plus_tax: "mais taxas" - total_monthly_bill_incl_tax: "Total mensal (taxas inclusas)" min_bill_turnover_desc: "uma vez que o volume de negócio exceder %{mbt_amount}" - business_model_configuration: "Configuração do modelo de negócios" say_no: "Não" say_yes: "Sim" then: então @@ -78,6 +74,51 @@ pt-BR: tag_has_rules: "Regras existentes para essa tag: %{num}" has_one_rule: "possui uma regra" has_n_rules: "tem %{num} regras" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Contas e Faturamento" + accounts_administration_distributor: "distribuidor de administração de contas" + admin_settings: "Preferências do Sistema" + update_invoice: "Atualizar faturas" + finalise_invoice: "Finalizar Faturas" + finalise_user_invoices: "Finalizar Faturas de Usuário" + finalise_user_invoice_explained: "Usar este botão para finalizar todos as faturas no sistema para o calendário do mês anterior. " + manually_run_task: "Rodar Tarefa Manualmente" + update_user_invoices: "Atualizar Fatura de Usuário" + update_user_invoice_explained: "Usar este botão para atualizar imediamente todas as faturas no sistema para o mês atual, para cada usuário da empresa no sistema. Essa tarefa pode ser automatizada para rodar automaticamente toda noite. " + auto_finalise_invoices: "Finalizar automaticamente as faturas no dia 2 de cada mês, à 1:30am" + auto_update_invoices: "Atualizar automaticamente faturas toda as noites, a 1:00 am" + business_model_configuration: + edit: + business_model_configuration: "Configuração do modelo de negócios" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Duração de Avaliação da Loja (dias)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: " \"Percentual de faturamento\"" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "limite mensal (taxas exclusas)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total mensal (taxas inclusas)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Adicionar Cliente" @@ -588,7 +629,6 @@ pt-BR: products_max_quantity: Quantidade máxima products_distributor: Distribuidor products_distributor_info: Quando você selecionar um distribuidor para seu pedido, o endereço e data para retirada serão exibidos aqui. - shop_trial_length: "Duração de Avaliação da Loja (dias)" shop_trial_expires_in: "O período de avaliação do mercado termina em " shop_trial_expired_notice: "Boa notícia! Decidimos extender o período avaliação do mercado até segunda ordem. " password: Senha @@ -811,16 +851,6 @@ pt-BR: roles: "Papeis" update: "Atualizar" add_producer_property: "Adicionar produtor" - admin_settings: "Preferências do Sistema" - update_invoice: "Atualizar faturas" - finalise_invoice: "Finalizar Faturas" - finalise_user_invoices: "Finalizar Faturas de Usuário" - finalise_user_invoice_explained: "Usar este botão para finalizar todos as faturas no sistema para o calendário do mês anterior. " - manually_run_task: "Rodar Tarefa Manualmente" - update_user_invoices: "Atualizar Fatura de Usuário" - update_user_invoice_explained: "Usar este botão para atualizar imediamente todas as faturas no sistema para o mês atual, para cada usuário da empresa no sistema. Essa tarefa pode ser automatizada para rodar automaticamente toda noite. " - auto_finalise_invoices: "Finalizar automaticamente as faturas no dia 2 de cada mês, à 1:30am" - auto_update_invoices: "Atualizar automaticamente faturas toda as noites, a 1:00 am" in_progress: "Em andamento" started_at: "Começou em " queued: "Aguardando" @@ -831,8 +861,6 @@ pt-BR: no_customers_found: "Nenhum cliente encontrado" go: "Ir" hub: "Central" - accounts_administration_distributor: "distribuidor de administração de contas" - accounts_and_billing: "Contas e Faturamento" producer: "Produtor" product: "Produto" price: "Preço" diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 485cb18a3f..66548ea241 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -39,16 +39,12 @@ sv: must_have_valid_business_number: "%{enterprise_name} måste ha ett giltigt organisationsnummer innan fakturor kan skickas." invoice: "Faktura" percentage_of_sales: "%{percentage} av försäljning" - percentage_of_turnover: "Procent av omsättning" - monthly_cap_excl_tax: "månatligt tak (exkl. moms)" capped_at_cap: "begränsat till %{cap}" per_month: "per månad" free: "gratis" free_trial: "prova gratis" plus_tax: "plus Moms" - total_monthly_bill_incl_tax: "Total Månadskostnad (Inkl. Skatter)" min_bill_turnover_desc: "när omsättning överskrider %{mbt_amount}" - business_model_configuration: "Konfigurera affärsmodell" say_no: "Nej" say_yes: "Ja" then: då @@ -81,6 +77,51 @@ sv: tag_has_rules: "Regler för denna tagg: %{num}" has_one_rule: "har en regel" has_n_rules: "har %{num} regler" + accounts_and_billing_settings: + method_settings: + default_accounts_payment_method: "Default Accounts Payment Method" + default_accounts_shipping_method: "Default Accounts Shipping Method" + edit: + accounts_and_billing: "Konton och fakturering" + accounts_administration_distributor: "distributör av bokföringsadministration" + admin_settings: "Inställningar" + update_invoice: "Uppdatera fakturor" + finalise_invoice: "Slutför fakturor" + finalise_user_invoices: "Slutför användarafakturor" + finalise_user_invoice_explained: "Använd den här knappen för att slutföra alla fakturor i systemet för den gångna månaden. Denna uppgift ställas in så att den utförs automatiskt en gång per månad." + manually_run_task: "Manuellt utförda uppgifter" + update_user_invoices: "Uppdatera användarfakturor" + update_user_invoice_explained: "Använd denna knapp för att omedelbart uppdatera alla fakturor innevarande månad för alla företag i systemet. Den här uppgiften kan ställas in så att den automatiskt utförs varje natt." + auto_finalise_invoices: "Automatisk summering av fakturor den 2:a kl 01.30 " + auto_update_invoices: "Automatisk uppdatering av fakturor varje natt kl 01.00" + business_model_configuration: + edit: + business_model_configuration: "Konfigurera affärsmodell" + business_model_configuration_tip: "Configure the rate at which shops will be charged each month for use of the Open Food Network." + bill_calculation_settings: "Bill Calculation Settings" + bill_calculation_settings_tip: "Adjust the amount that enterprises will be billed each month for use of the OFN." + shop_trial_length: "Försökstiden är (dagar)" + shop_trial_length_tip: "The length of time (in days) that enterprises who are set up as shops can run as a trial period." + fixed_monthly_charge: "Fixed Monthly Charge" + fixed_monthly_charge_tip: "A fixed monthly charge for all enterprises who are set up as a shop and have exceeded the minimum billable turnover (if set)." + percentage_of_turnover: "Procent av omsättning" + percentage_of_turnover_tip: "When greater than zero, this rate (0.0 - 1.0) will be applied to the total turnover of each shop and added to any fixed charges (to the left) to calculate the monthly bill." + monthly_cap_excl_tax: "månatligt tak (exkl. moms)" + monthly_cap_excl_tax_tip: "When greater than zero, this value will be used as a cap on the amount that shops will be charged each month." + tax_rate: "Tax Rate" + tax_rate_tip: "Tax rate that applies to the the monthly bill that enterprises are charged for using the system." + minimum_monthly_billable_turnover: "Minimum Monthly Billable Turnover" + minimum_monthly_billable_turnover_tip: "Minimum monthly turnover before a shopfront will be charged for using OFN. Enterprises turning over less than this amount in a month will not be charged, either as a percentage or fixed rate." + example_bill_calculator: "Example Bill Calculator" + example_bill_calculator_legend: "Alter the example turnover to visualise the effect of the settings to the left." + example_monthly_turnover: "Example Monthly Turnover" + example_monthly_turnover_tip: "An example monthly turnover for an enterprise which will be used to generate calculate an example monthly bill below." + cap_reached?: "Cap Reached ?" + cap_reached?_tip: "Whether the cap (specified to the left) has been reached, given the settings and the turnover provided." + included_tax: "Included tax" + included_tax_tip: "The total tax included in the example monthly bill, given the settings and the turnover provided." + total_monthly_bill_incl_tax: "Total Månadskostnad (Inkl. Skatter)" + total_monthly_bill_incl_tax_tip: "The example total monthly bill with tax included, given the settings and the turnover provided." customers: index: add_customer: "Lägg till kund" @@ -594,7 +635,6 @@ sv: products_max_quantity: Maxkvantitet products_distributor: Distributör products_distributor_info: När du väljer distributör för din order kommer leveranstider att visas här - shop_trial_length: "Försökstiden är (dagar)" shop_trial_expires_in: "Din försökstid för skyltfönster gå ut om" shop_trial_expired_notice: "Goda nyheter! Vi har beslutat utöka skyltfönstrets försökstid tills vidare. " password: Lösenord @@ -823,16 +863,6 @@ sv: roles: "Uppgifter" update: "Uppdatera" add_producer_property: "Lägg till producentegenskaper" - admin_settings: "Inställningar" - update_invoice: "Uppdatera fakturor" - finalise_invoice: "Slutför fakturor" - finalise_user_invoices: "Slutför användarafakturor" - finalise_user_invoice_explained: "Använd den här knappen för att slutföra alla fakturor i systemet för den gångna månaden. Denna uppgift ställas in så att den utförs automatiskt en gång per månad." - manually_run_task: "Manuellt utförda uppgifter" - update_user_invoices: "Uppdatera användarfakturor" - update_user_invoice_explained: "Använd denna knapp för att omedelbart uppdatera alla fakturor innevarande månad för alla företag i systemet. Den här uppgiften kan ställas in så att den automatiskt utförs varje natt." - auto_finalise_invoices: "Automatisk summering av fakturor den 2:a kl 01.30 " - auto_update_invoices: "Automatisk uppdatering av fakturor varje natt kl 01.00" in_progress: "Under bearbetning" started_at: "Startade kl" queued: "Köad" @@ -843,8 +873,6 @@ sv: no_customers_found: "Inga kunder hittade" go: "Kör igång" hub: "Matställe" - accounts_administration_distributor: "distributör av bokföringsadministration" - accounts_and_billing: "Konton och fakturering" producer: "Producent" product: "Produkt" price: "Pris" diff --git a/config/routes.rb b/config/routes.rb index 607e6308a2..04ad87568e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -145,6 +145,8 @@ Openfoodnetwork::Application.routes.draw do resources :column_preferences, only: [], format: :json do put :bulk_update, on: :collection end + + resource :invoice_settings, only: [:edit, :update] end namespace :api do @@ -247,6 +249,7 @@ Spree::Core::Engine.routes.prepend do resources :orders do get :invoice, on: :member get :print, on: :member + get :print_ticket, on: :member get :managed, on: :collection end diff --git a/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb b/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb new file mode 100644 index 0000000000..d9cfca91ba --- /dev/null +++ b/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb @@ -0,0 +1,6 @@ +class AddInvoiceTextAndInvoiceLogoToEnterprises < ActiveRecord::Migration + def change + add_column :enterprises, :invoice_text, :text + add_column :enterprises, :display_invoice_logo, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 64bfd0df69..65e413e92b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20160921060442) do +ActiveRecord::Schema.define(:version => 20161215230219) do create_table "account_invoices", :force => true do |t| t.integer "user_id", :null => false @@ -249,6 +249,8 @@ ActiveRecord::Schema.define(:version => 20160921060442) do t.string "email_address" t.boolean "require_login", :default => false, :null => false t.boolean "allow_guest_orders", :default => true, :null => false + t.text "invoice_text" + t.boolean "display_invoice_logo", :default => false end add_index "enterprises", ["address_id"], :name => "index_enterprises_on_address_id" diff --git a/lib/open_food_network/sales_tax_report.rb b/lib/open_food_network/sales_tax_report.rb index 0d41b24ec1..442286a61a 100644 --- a/lib/open_food_network/sales_tax_report.rb +++ b/lib/open_food_network/sales_tax_report.rb @@ -9,9 +9,27 @@ module OpenFoodNetwork end def header - ["Order number", "Date", "Items", "Items total (#{currency_symbol})", "Taxable Items Total (#{currency_symbol})", - "Sales Tax (#{currency_symbol})", "Delivery Charge (#{currency_symbol})", "Tax on Delivery (#{currency_symbol})", "Tax on Fees (#{currency_symbol})", - "Total Tax (#{currency_symbol})", "Customer", "Distributor"] + case params[:report_type] + when "tax_rates" + [I18n.t(:report_header_order_number), + I18n.t(:report_header_total_excl_vat, currency_symbol: currency_symbol)] + + relevant_rates.map { |rate| "%.1f%% (%s)" % [rate.to_f * 100, currency_symbol] } + + [I18n.t(:report_header_total_tax, currency_symbol: currency_symbol), + I18n.t(:report_header_total_incl_vat, currency_symbol: currency_symbol)] + else + [I18n.t(:report_header_order_number), + I18n.t(:report_header_date), + I18n.t(:report_header_items), + I18n.t(:report_header_items_total, currency_symbol: currency_symbol), + I18n.t(:report_header_taxable_items_total, currency_symbol: currency_symbol), + I18n.t(:report_header_sales_tax, currency_symbol: currency_symbol), + I18n.t(:report_header_delivery_charge, currency_symbol: currency_symbol), + I18n.t(:report_header_tax_on_delivery, currency_symbol: currency_symbol), + I18n.t(:report_header_tax_on_fees, currency_symbol: currency_symbol), + I18n.t(:report_header_total_tax, currency_symbol: currency_symbol), + I18n.t(:report_header_customer), + I18n.t(:report_header_distributor)] + end end def search @@ -24,19 +42,33 @@ module OpenFoodNetwork end def table - orders.map do |order| - totals = totals_of order.line_items - shipping_cost = shipping_cost_for order + case params[:report_type] + when "tax_rates" + orders.map do |order| + [order.number, order.total - order.total_tax] + + relevant_rates.map { |rate| order.tax_adjustment_totals.fetch(rate, 0) } + + [order.total_tax, order.total] + end + else + orders.map do |order| + totals = totals_of order.line_items + shipping_cost = shipping_cost_for order - [order.number, order.created_at, totals[:items], totals[:items_total], - totals[:taxable_total], totals[:sales_tax], shipping_cost, order.shipping_tax, order.enterprise_fee_tax, order.total_tax, - order.bill_address.full_name, order.distributor.andand.name] + [order.number, order.created_at, totals[:items], totals[:items_total], + totals[:taxable_total], totals[:sales_tax], shipping_cost, order.shipping_tax, order.enterprise_fee_tax, order.total_tax, + order.bill_address.full_name, order.distributor.andand.name] + end end end private + def relevant_rates + return @relevant_rates unless @relevant_rates.nil? + @relevant_rates = Spree::TaxRate.pluck(:amount).uniq + end + def totals_of(line_items) totals = {items: 0, items_total: 0.0, taxable_total: 0.0, sales_tax: 0.0} diff --git a/spec/features/admin/business_model_configuration_spec.rb b/spec/features/admin/business_model_configuration_spec.rb index ab5e4fd2e7..a16a23976e 100644 --- a/spec/features/admin/business_model_configuration_spec.rb +++ b/spec/features/admin/business_model_configuration_spec.rb @@ -42,7 +42,7 @@ feature 'Business Model Configuration' do click_button "Update" - expect(page).to have_content "Business model configuration has been successfully updated!" + expect(page).to have_content "Business Model has been successfully updated!" expect(Spree::Config.account_invoices_monthly_fixed).to eq 10 expect(Spree::Config.account_invoices_monthly_rate).to eq 0.05 expect(Spree::Config.account_invoices_monthly_cap).to eq 30 diff --git a/spec/features/admin/reports_spec.rb b/spec/features/admin/reports_spec.rb index e2c991a185..2a63d73216 100644 --- a/spec/features/admin/reports_spec.rb +++ b/spec/features/admin/reports_spec.rb @@ -199,6 +199,7 @@ feature %q{ login_to_admin_as user1 click_link "Reports" click_link "Sales Tax" + select("Tax types", from: "report_type") end it "reports" do diff --git a/spec/features/consumer/registration_spec.rb b/spec/features/consumer/registration_spec.rb index 5cd34206a5..f6a90f6f61 100644 --- a/spec/features/consumer/registration_spec.rb +++ b/spec/features/consumer/registration_spec.rb @@ -1,14 +1,17 @@ require 'spec_helper' feature "Registration", js: true do + include AuthenticationWorkflow include WebHelper describe "Registering a Profile" do let(:user) { create(:user, password: "password", password_confirmation: "password") } + before { Spree::Config.enterprises_require_tos = false } it "Allows a logged in user to register a profile" do visit registration_path + expect(Spree::Config.enterprises_require_tos).to eq false expect(URI.parse(current_url).path).to eq registration_auth_path page.has_selector? "dd", text: "Login" @@ -23,7 +26,7 @@ feature "Registration", js: true do # Done reading introduction page.has_content? - click_and_ensure(:button, "Let's get started!", lambda { page.has_content? 'Woot!' }) + perform_and_ensure(:click_button, "Let's get started!", lambda { page.has_content? 'Woot!' }) # Filling in details fill_in 'enterprise_name', with: "My Awesome Enterprise" @@ -34,18 +37,18 @@ feature "Registration", js: true do fill_in 'enterprise_zipcode', with: '3070' select 'Australia', from: 'enterprise_country' select 'VIC', from: 'enterprise_state' - click_and_ensure(:button, "Continue", lambda { page.has_content? 'Who is responsible for managing My Awesome Enterprise?' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Who is responsible for managing My Awesome Enterprise?' }) # Filling in Contact Details fill_in 'enterprise_contact', with: 'Saskia Munroe' page.should have_field 'enterprise_email_address', with: user.email fill_in 'enterprise_phone', with: '12 3456 7890' - click_and_ensure(:button, "Continue", lambda { page.has_content? 'Last step to add My Awesome Enterprise!' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Last step to add My Awesome Enterprise!' }) # Choosing a type - click_and_ensure(:link, 'producer-panel', lambda { page.has_content? '#producer-panel.selected' } ) - click_and_ensure(:button, "Create Profile", lambda { page.has_content? 'Nice one!' }) + perform_and_ensure(:click_link, 'producer-panel', lambda { page.has_selector? '#producer-panel.selected' } ) + perform_and_ensure(:click_button, "Create Profile", lambda { page.has_content? 'Nice one!' }) # Enterprise should be created e = Enterprise.find_by_name('My Awesome Enterprise') @@ -60,7 +63,7 @@ feature "Registration", js: true do fill_in 'enterprise_abn', with: '12345' fill_in 'enterprise_acn', with: '54321' choose 'Yes' # enterprise_charges_sales_tax - click_and_ensure(:button, "Continue", lambda { page.has_content? 'Step 1. Select Logo Image' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Step 1. Select Logo Image' }) # Enterprise should be updated e.reload @@ -72,10 +75,10 @@ feature "Registration", js: true do # Images # Move from logo page - click_and_ensure(:button, "Continue", lambda { page.has_content? 'Step 3. Select Promo Image' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Step 3. Select Promo Image' }) # Move from promo page - click_and_ensure(:button, "Continue", lambda { page.has_content? 'How can people find My Awesome Enterprise online?' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'How can people find My Awesome Enterprise online?' }) # Filling in social fill_in 'enterprise_website', with: 'www.shop.com' @@ -83,7 +86,7 @@ feature "Registration", js: true do fill_in 'enterprise_linkedin', with: 'LiNkEdIn' fill_in 'enterprise_twitter', with: '@TwItTeR' fill_in 'enterprise_instagram', with: '@InStAgRaM' - click_and_ensure(:button, "Continue", lambda { page.has_content? 'Finished!' }) + perform_and_ensure(:click_button, "Continue", lambda { page.has_content? 'Finished!' }) # Done expect(page).to have_content "We've sent a confirmation email to #{user.email} if it hasn't been activated before." @@ -94,6 +97,42 @@ feature "Registration", js: true do expect(e.twitter).to eq "@TwItTeR" expect(e.instagram).to eq "@InStAgRaM" end + + end + + describe "Terms of Service agreement" do + let!(:user2) { create(:user) } + + before do + quick_login_as user2 + end + + context "if accepting Terms of Service is not required" do + before { Spree::Config.enterprises_require_tos = false } + + it "allows registration as normal" do + visit registration_path + + click_button "Let's get started!" + find("div#progress-bar").visible?.should be_true + end + end + + context "if accepting Terms of Service is required" do + before { Spree::Config.enterprises_require_tos = true } + + it "does not allow registration unless checkbox is checked" do + visit registration_path + + expect(page).to have_content "Terms of Service" + expect(page).to have_selector "input.button.primary[disabled]" + + perform_and_ensure(:check, "accept_terms", lambda { page.has_no_selector? "input.button.primary[disabled]" }) + + click_button "Let's get started!" + find("div#progress-bar").visible?.should be_true + end + end end def switch_to_login_tab @@ -117,13 +156,16 @@ feature "Registration", js: true do expect(page).to have_content content end - def click_and_ensure(type, text, check) - # Buttons appear to be unresponsive for a while, so keep clicking them until content appears + def perform_and_ensure(action, *args, assertion) + # Buttons/Links/Checkboxes appear to be unresponsive for a while + # so keep clicking them until assertion is satified using_wait_time 0.5 do 10.times do - send("click_#{type}", text) - break if check.call + send(action, *args) + return if assertion.call end + # Only make it here if we have tried 10 times + expect(assertion.call).to be true end end end