From 68dd595701844b1aa6cac4d5c6863b1348d8c8b4 Mon Sep 17 00:00:00 2001 From: Regene27 Date: Thu, 25 Apr 2024 15:17:44 +0700 Subject: [PATCH 1/3] Close #1348 Edit customer can have multiple taxons and add location field --- .../spree/billing/customers_controller.rb | 2 +- .../spree/billing/places_controller.rb | 35 ++++++++ app/models/spree_cm_commissioner/customer.rb | 25 +++--- .../spree_cm_commissioner/customer_taxon.rb | 6 ++ .../spree_cm_commissioner/order_decorator.rb | 4 +- app/models/spree_cm_commissioner/place.rb | 10 ++- .../spree_cm_commissioner/taxon_decorator.rb | 1 + .../spree/billing/customers/_form.html.erb | 21 ++--- .../spree/billing/customers/index.html.erb | 27 +++--- .../spree/billing/orders/_search.html.erb | 4 +- app/views/spree/billing/orders/index.html.erb | 4 +- app/views/spree/billing/places/_form.html.erb | 9 ++ app/views/spree/billing/places/edit.html.erb | 12 +++ app/views/spree/billing/places/index.html.erb | 36 ++++++++ app/views/spree/billing/places/new.html.erb | 15 ++++ .../report/active_subscribers.html.erb | 6 +- .../spree/billing/shared/_main_menu.html.erb | 3 + config/locales/en.yml | 1 + config/routes.rb | 1 + ...0240424080551_create_cm_customer_taxons.rb | 12 +++ ...042912_remove_taxon_id_from_cm_customer.rb | 5 ++ ...40429080434_add_place_id_to_cm_customer.rb | 5 ++ .../factories/customers_taxons_factory.rb | 6 ++ .../spree_cm_commissioner/customer_spec.rb | 83 +++++++++---------- 24 files changed, 235 insertions(+), 98 deletions(-) create mode 100644 app/controllers/spree/billing/places_controller.rb create mode 100644 app/models/spree_cm_commissioner/customer_taxon.rb create mode 100644 app/views/spree/billing/places/_form.html.erb create mode 100644 app/views/spree/billing/places/edit.html.erb create mode 100644 app/views/spree/billing/places/index.html.erb create mode 100644 app/views/spree/billing/places/new.html.erb create mode 100644 db/migrate/20240424080551_create_cm_customer_taxons.rb create mode 100644 db/migrate/20240425042912_remove_taxon_id_from_cm_customer.rb create mode 100644 db/migrate/20240429080434_add_place_id_to_cm_customer.rb create mode 100644 lib/spree_cm_commissioner/test_helper/factories/customers_taxons_factory.rb diff --git a/app/controllers/spree/billing/customers_controller.rb b/app/controllers/spree/billing/customers_controller.rb index c54be089f..49ddd7dae 100644 --- a/app/controllers/spree/billing/customers_controller.rb +++ b/app/controllers/spree/billing/customers_controller.rb @@ -9,7 +9,7 @@ def collection return @collection if defined?(@collection) @search = current_vendor.customers.ransack(params[:q]) - @collection = @search.result.includes(:subscriptions, :taxon).page(page).per(per_page) + @collection = @search.result.includes(:subscriptions, :taxons).page(page).per(per_page) end def load_customer diff --git a/app/controllers/spree/billing/places_controller.rb b/app/controllers/spree/billing/places_controller.rb new file mode 100644 index 000000000..64be31d67 --- /dev/null +++ b/app/controllers/spree/billing/places_controller.rb @@ -0,0 +1,35 @@ +module Spree + module Billing + class PlacesController < Spree::Billing::BaseController + before_action :load_place, if: -> { member_action? } + + def collection + params[:q] = {} if params[:q].blank? + places = SpreeCmCommissioner::Place.where(name: %w[KR KRS KSD]) + + @search = places.ransack(params[:q]) + @collection = @search.result.page(page).per(per_page) + end + + def load_place + @place = @object + end + + def location_after_save + billing_places_url + end + + def model_class + SpreeCmCommissioner::Place + end + + def object_name + 'spree_cm_commissioner_place' + end + + def collection_url(options = {}) + billing_places_url(options) + end + end + end +end diff --git a/app/models/spree_cm_commissioner/customer.rb b/app/models/spree_cm_commissioner/customer.rb index 2ee65ac9d..50c8a953d 100644 --- a/app/models/spree_cm_commissioner/customer.rb +++ b/app/models/spree_cm_commissioner/customer.rb @@ -2,15 +2,15 @@ module SpreeCmCommissioner class Customer < SpreeCmCommissioner::Base include SpreeCmCommissioner::PhoneNumberSanitizer - before_validation :generate_sequence_number, if: -> { sequence_number.nil? } + before_validation :generate_sequence_number, if: -> { sequence_number.nil? || place_id_changed? } before_validation :assign_number, if: -> { number.nil? } before_validation :clone_billing_address, if: :use_billing? attr_accessor :use_billing belongs_to :vendor, class_name: 'Spree::Vendor' - belongs_to :taxon, class_name: 'Spree::Taxon' belongs_to :user, class_name: 'Spree::User', optional: true + belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: true belongs_to :bill_address, class_name: 'Spree::Address', optional: true @@ -25,13 +25,14 @@ class Customer < SpreeCmCommissioner::Base has_many :suspended_subscriptions, -> { suspended }, class_name: 'SpreeCmCommissioner::Subscription', dependent: :destroy has_many :orders, class_name: 'Spree::Order', through: :subscriptions + has_many :customer_taxons, class_name: 'SpreeCmCommissioner::CustomerTaxon', dependent: :destroy + has_many :taxons, through: :customer_taxons, class_name: 'Spree::Taxon' has_one :latest_subscription, -> { order(created_at: :desc) }, class_name: 'SpreeCmCommissioner::Subscription' has_many :variants, class_name: 'Spree::Variant', through: :subscriptions has_many :active_variants, class_name: 'Spree::Variant', through: :active_subscriptions, source: :variant - validates :sequence_number, presence: true, uniqueness: { scope: :vendor_id } validates :email, uniqueness: { scope: :vendor_id }, allow_blank: true, unless: -> { Spree::Store.default.code.include?('billing') } validates :phone_number, uniqueness: { scope: :vendor_id }, allow_blank: true, unless: -> { Spree::Store.default.code.include?('billing') } validates :number, presence: true, uniqueness: { scope: :vendor_id } @@ -39,19 +40,18 @@ class Customer < SpreeCmCommissioner::Base validate :billing_customer_attributes acts_as_paranoid - self.whitelisted_ransackable_attributes = %w[number phone_number first_name last_name taxon_id sequence_number] + self.whitelisted_ransackable_attributes = %w[number phone_number first_name last_name sequence_number place_id] + self.whitelisted_ransackable_associations = %w[taxons] accepts_nested_attributes_for :ship_address, :bill_address def generate_sequence_number - return if sequence_number.present? - - last_customer = vendor.customers.last - self.sequence_number = last_customer.present? ? last_customer.sequence_number.to_i + 1 : 1 + last_customer_with_same_place = vendor.customers.where(place_id: place_id).where.not(id: id).last + self.sequence_number = last_customer_with_same_place.present? ? last_customer_with_same_place.sequence_number.to_i + 1 : 1 end def customer_number - "#{vendor.code}-#{sequence_number.to_s.rjust(6, '0')}" + "#{place&.name}-#{sequence_number.to_s.rjust(6, '0')}" end def assign_number @@ -93,7 +93,9 @@ def subscribable_variants vendor.variants .joins('INNER JOIN spree_products as p ON p.id = spree_variants.product_id AND p.subscribable = TRUE') .joins('INNER JOIN spree_products_taxons as pt ON pt.product_id = p.id') - .joins("INNER JOIN cm_customers as c on c.taxon_id = pt.taxon_id AND c.id = #{id}") + .joins("INNER JOIN cm_customers as c on c.id = #{id}") + .joins('INNER JOIN cm_customer_taxons as ct on ct.customer_id = c.id') + .joins('INNER JOIN spree_taxons as t on t.id = pt.taxon_id AND t.id = ct.taxon_id') .where('spree_variants.is_master = FALSE AND spree_variants.deleted_at IS NULL') end @@ -105,9 +107,8 @@ def billing_customer_attributes return unless Spree::Store.default.code.include?('billing') errors.add(:base, :owner_name_cant_be_blank) if last_name.blank? - errors.add(:base, :taxon_cant_be_blank) if taxon.blank? + errors.add(:base, :taxon_cant_be_blank) if taxons.blank? errors.add(:base, :phone_number_cant_be_blank) if phone_number.blank? - errors.add(:base, :quantity_cant_be_less_than_or_equal_to_zero) if quantity <= 0 end end end diff --git a/app/models/spree_cm_commissioner/customer_taxon.rb b/app/models/spree_cm_commissioner/customer_taxon.rb new file mode 100644 index 000000000..4b2f755ae --- /dev/null +++ b/app/models/spree_cm_commissioner/customer_taxon.rb @@ -0,0 +1,6 @@ +module SpreeCmCommissioner + class CustomerTaxon < Base + belongs_to :customer, class_name: 'SpreeCmCommissioner::Customer' + belongs_to :taxon, class_name: 'Spree::Taxon' + end +end diff --git a/app/models/spree_cm_commissioner/order_decorator.rb b/app/models/spree_cm_commissioner/order_decorator.rb index 0fba53fcc..9316112d0 100644 --- a/app/models/spree_cm_commissioner/order_decorator.rb +++ b/app/models/spree_cm_commissioner/order_decorator.rb @@ -24,13 +24,13 @@ def self.prepended(base) base.belongs_to :subscription, class_name: 'SpreeCmCommissioner::Subscription', optional: true base.has_many :customer, class_name: 'SpreeCmCommissioner::Customer', through: :subscription - base.has_many :taxon, class_name: 'Spree::Taxon', through: :customer + base.has_many :taxons, class_name: 'Spree::Taxon', through: :customer base.has_many :vendors, through: :products, class_name: 'Spree::Vendor' base.has_many :taxons, through: :products, class_name: 'Spree::Taxon' base.delegate :customer, to: :subscription, allow_nil: true - base.whitelisted_ransackable_associations |= %w[customer taxon payments] + base.whitelisted_ransackable_associations |= %w[customer taxons payments] base.whitelisted_ransackable_attributes |= %w[phone_number email number] base.after_update :precalculate_conversion, if: -> { state_changed_to_complete? } diff --git a/app/models/spree_cm_commissioner/place.rb b/app/models/spree_cm_commissioner/place.rb index af7531b08..bab1c8720 100644 --- a/app/models/spree_cm_commissioner/place.rb +++ b/app/models/spree_cm_commissioner/place.rb @@ -2,11 +2,15 @@ module SpreeCmCommissioner class Place < ApplicationRecord - validates :reference, presence: true - validates :lat, presence: true - validates :lon, presence: true + validates :reference, presence: true, unless: -> { Spree::Store.default.code.include?('billing') } + validates :lat, presence: true, unless: -> { Spree::Store.default.code.include?('billing') } + validates :lon, presence: true, unless: -> { Spree::Store.default.code.include?('billing') } has_many :nearby_places, class_name: 'SpreeCmCommissioner::VendorPlace', dependent: :destroy has_many :vendors, through: :nearby_places, source: :vendor, class_name: 'Spree::Vendor' + + def self.ransackable_attributes(auth_object = nil) + super & %w[name] + end end end diff --git a/app/models/spree_cm_commissioner/taxon_decorator.rb b/app/models/spree_cm_commissioner/taxon_decorator.rb index 4a995bdda..ea92847d2 100644 --- a/app/models/spree_cm_commissioner/taxon_decorator.rb +++ b/app/models/spree_cm_commissioner/taxon_decorator.rb @@ -15,6 +15,7 @@ def self.prepended(base) base.has_many :products, through: :classifications, class_name: 'Spree::Product' base.has_many :guests, foreign_key: :event_id, class_name: 'SpreeCmCommissioner::Guest', dependent: :nullify base.has_many :check_ins, as: :checkinable, class_name: 'SpreeCmCommissioner::CheckIn', dependent: :nullify + base.has_many :customer_taxons, class_name: 'SpreeCmCommissioner::CustomerTaxon' base.has_one :category_icon, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonCategoryIcon' diff --git a/app/views/spree/billing/customers/_form.html.erb b/app/views/spree/billing/customers/_form.html.erb index bf147b9a1..d3329c246 100644 --- a/app/views/spree/billing/customers/_form.html.erb +++ b/app/views/spree/billing/customers/_form.html.erb @@ -15,10 +15,10 @@ <%= f.text_field :last_name, class: 'form-control' %> <%= f.error_message_on :last_name %> <% end %> - <%= f.field_container :gender do %> - <%= f.label :gender, Spree.t(:gender) %> - <%= f.select(:gender, Spree::User.genders.keys, { include_blank: true }, { class: 'select2-clear' }) %> - <%= f.error_message_on :gender %> + <%= f.field_container :place_id do %> + <%= f.label :place_id, Spree.t(:location) %> + <%= f.collection_select(:place_id, SpreeCmCommissioner::Place.where(name: %w[KR KRS KSD]), :id, :name, { include_blank: true }, { class: 'select2-clear' }) %> + <%= f.error_message_on :location %> <% end %> <%= f.field_container :phone_number do %> <%= f.label :phone_number, I18n.t('activerecord.attributes.spree/order.phone_number') %> @@ -26,15 +26,10 @@ <%= f.error_message_on :phone_number %> <% end %> <%= f.hidden_field :vendor_id, value: current_vendor.id %> - <%= f.field_container :taxon_id do %> - <%= f.label :taxon_id, I18n.t('activerecord.attributes.spree/order.taxon') %> - <%= f.collection_select(:taxon_id, Spree::Taxon.where('depth > ? ',0).order('parent_id ASC').uniq, :id, :pretty_name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2' })%> - <%= f.error_message_on :taxon_id %> - <% end %> - <%= f.field_container :quantity do %> - <%= f.label :quantity, I18n.t('activerecord.attributes.spree/order.quantity') %> - <%= f.number_field :quantity, class: 'form-control' %> - <%= f.error_message_on :quantity %> + <%= f.field_container :taxons do %> + <%= f.label :taxon_ids, I18n.t('activerecord.attributes.spree/order.taxon') %> + <%= f.collection_select(:taxon_ids, Spree::Taxon.where('depth > ? ',0).order('parent_id ASC').uniq, :id, :pretty_name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', multiple: true })%> + <%= f.error_message_on :taxon_ids %> <% end %> diff --git a/app/views/spree/billing/customers/index.html.erb b/app/views/spree/billing/customers/index.html.erb index f200876cc..981114570 100644 --- a/app/views/spree/billing/customers/index.html.erb +++ b/app/views/spree/billing/customers/index.html.erb @@ -17,30 +17,29 @@
<%= f.label :number_cont, Spree.t(:customer_number) %>
-
- <%= @current_vendor.code %>- -
<%= f.text_field :number_cont, class: "form-control js-filterable" %>
-
+
- <%= f.label :first_name_cont, Spree.t(:first_name) %> - <%= f.text_field :first_name_cont, class: 'form-control js-filterable' %> + <%= f.label :first_name_or_last_name_cont, Spree.t(:name) %> + <%= f.text_field :first_name_or_last_name_cont, class: 'form-control js-filterable' %>
-
+
- <%= f.label :last_name_cont, Spree.t(:last_name) %> - <%= f.text_field :last_name_cont, class: 'form-control js-filterable' %> + <%= f.label :taxons_id_eq, Spree.t(:type) %> + <%= f.collection_select(:taxons_id_eq, Spree::Taxon.all.uniq, :id, :pretty_name, { include_blank: true }, { class: 'select2 form-control js-filterable' }) %>
-
+
+
+
- <%= f.label :taxon_id_eq, Spree.t(:type) %> - <%= f.select :taxon_id_eq, Spree::Taxon.all.map{|t| [t.name , t.id]}, { include_blank: true}, class: 'form-control js-filterable' %> + <%= f.label :place_id_eq, Spree.t(:location) %> + <%= f.collection_select(:place_id_eq, SpreeCmCommissioner::Place.where(name: %w[KR KRS KSD]), :id, :name, { include_blank: true }, { class: "select2 form-control js-filterable" }) %>
@@ -66,7 +65,7 @@ <%= sort_link @search, :phone_number, Spree.t(:phone_number), {}, {title: 'phone_number_title'} %> - <%= sort_link @search, :taxon_id, Spree.t(:type), {}, {title: 'taxon_title'} %> + <%= sort_link @search, :taxons_id, Spree.t(:type), {}, {title: 'taxon_title'} %> <%= sort_link @search, :created_at, Spree.t(:created_at),{},{title:'created_at_title'} %> @@ -100,7 +99,7 @@ <%= customer.phone_number %> - <%= customer.taxon&.name %> + <%= customer.taxons.map(&:name).join(' ') %> <%= customer.created_at.to_date %> diff --git a/app/views/spree/billing/orders/_search.html.erb b/app/views/spree/billing/orders/_search.html.erb index 6bb00983d..e751f9fba 100644 --- a/app/views/spree/billing/orders/_search.html.erb +++ b/app/views/spree/billing/orders/_search.html.erb @@ -22,8 +22,8 @@
- <%= f.label :taxon_permalink_cont, I18n.t(:taxon, scope: 'activerecord.attributes.spree/order') %> - <%= f.select :taxon_permalink_cont, Spree::Taxon.all.map{|s| [s.name, s.permalink]}, {include_blank: true}, class: 'select2-clear js-filterable' %> + <%= f.label :customer_taxons_id_eq, I18n.t(:taxon, scope: 'activerecord.attributes.spree/order') %> + <%= f.collection_select(:customer_taxons_id_eq, Spree::Taxon.all.uniq, :id, :pretty_name, { include_blank: true }, { class: 'select2 form-control js-filterable' }) %>
diff --git a/app/views/spree/billing/orders/index.html.erb b/app/views/spree/billing/orders/index.html.erb index b2cc359e9..f468eb1fb 100644 --- a/app/views/spree/billing/orders/index.html.erb +++ b/app/views/spree/billing/orders/index.html.erb @@ -32,8 +32,8 @@ <%= link_to order.customer.customer_number, edit_billing_customer_path(order.customer) %> <%= order.customer.phone_number %> - - <%= order.customer.taxon.name %> + + <% order.customer.taxons.map(&:name).join(' ') %> <%= order.display_total.to_html %> diff --git a/app/views/spree/billing/places/_form.html.erb b/app/views/spree/billing/places/_form.html.erb new file mode 100644 index 000000000..620dc191d --- /dev/null +++ b/app/views/spree/billing/places/_form.html.erb @@ -0,0 +1,9 @@ +
+
+ <%= f.field_container :name do %> + <%= f.label :name, Spree.t(:name) %> + <%= f.text_field :name, class: 'form-control' %> + <%= f.error_message_on :name %> + <% end %> +
+
diff --git a/app/views/spree/billing/places/edit.html.erb b/app/views/spree/billing/places/edit.html.erb new file mode 100644 index 000000000..d053a7b57 --- /dev/null +++ b/app/views/spree/billing/places/edit.html.erb @@ -0,0 +1,12 @@ +<% content_for :page_title do %> + <%= @place.name %> +<% end %> + +
+ <%= form_with model: @object, url: { action: 'update'} do |f| %> + <%= render partial: 'form', locals: {f: f} %> +
+ <%= render partial: 'spree/admin/shared/edit_resource_links', locals: { collection_url: spree.billing_places_path } %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/spree/billing/places/index.html.erb b/app/views/spree/billing/places/index.html.erb new file mode 100644 index 000000000..d755a5dd9 --- /dev/null +++ b/app/views/spree/billing/places/index.html.erb @@ -0,0 +1,36 @@ +<% content_for :page_title do %> + <%= plural_resource_name(SpreeCmCommissioner::Place) %> +<% end %> + +<% content_for :page_actions do %> + <%= button_link_to Spree.t(:new_place), new_billing_place_path, { class: "btn-success", icon: 'add.svg', id: 'admin_new_place' } %> +<% end if can?(:create, SpreeCmCommissioner::Place) %> + +<% if @places.any? %> +
+ + + + + + + + + <% @collection.each do |place| %> + + + + + <% end %> + +
<%= sort_link @search,:name, Spree.t(:name), { default_order: "desc" }, {title: 'admin_places_listing_name_title'} %>
+ <%= link_to place.name, edit_billing_place_path(place) %> + + + <%= link_to_edit place ,url: edit_billing_place_path(place) ,no_text: true if can?(:edit, place) %> + <%= link_to_delete place,url: billing_place_path(place), no_text: true if can?(:delete, place) %> + +
+
+ <%= render partial: 'spree/admin/shared/index_table_options', locals: { collection: @collection } %> +<% end %> \ No newline at end of file diff --git a/app/views/spree/billing/places/new.html.erb b/app/views/spree/billing/places/new.html.erb new file mode 100644 index 000000000..6ffa18cf5 --- /dev/null +++ b/app/views/spree/billing/places/new.html.erb @@ -0,0 +1,15 @@ +<% content_for :page_title do %> + <%= page_header_back_button spree.billing_places_path %> + <%= Spree.t(:new_place) %> +<% end %> +
+ <%= render partial: 'spree/admin/shared/error_messages', locals: { target: @object } %> +
+
+ <%= form_with model: @object, url: { action: 'create' } do |f| %> + <%= render partial: 'form', locals: { f: f } %> +
+ <%= render partial: 'spree/admin/shared/new_resource_links' %> +
+ <% end %> +
diff --git a/app/views/spree/billing/report/active_subscribers.html.erb b/app/views/spree/billing/report/active_subscribers.html.erb index 008701d12..f2fe24ab1 100644 --- a/app/views/spree/billing/report/active_subscribers.html.erb +++ b/app/views/spree/billing/report/active_subscribers.html.erb @@ -18,8 +18,8 @@ <%= f.text_field :sequence_number_cont, placeholder: I18n.t(:customer_id, scope: 'activerecord.attributes.spree/order'), class: "form-control js-filterable" %>
- <%= f.label :taxon_id_eq, I18n.t(:product_type, scope: 'activerecord.attributes.spree/order') %> - <%= f.select :taxon_id_eq, SpreeCmCommissioner::Customer.includes(:taxon).pluck(:taxon_id).uniq.map{ |taxon_id| [Spree::Taxon.find(taxon_id).name, taxon_id] }, { include_blank: true }, class: "select2-clear form-control js-filterable" %> + <%= f.label :taxons_id_eq, I18n.t(:product_type, scope: 'activerecord.attributes.spree/order') %> + <%= f.select :taxons_id_eq, SpreeCmCommissioner::Customer.includes(:taxons).pluck(:taxon_id).uniq.map{ |taxon_id| [Spree::Taxon.find(taxon_id).pretty_name, taxon_id] }, { include_blank: true }, class: "select2-clear form-control js-filterable" %>
<%= button Spree.t(:search), 'search.svg', nil, { class: 'btn-outline-primary' } %> @@ -71,7 +71,7 @@ <%= customer.phone_number %> - <%= customer.taxon.name %> + <%= customer.taxons.map(&:name).join(' ') %> <%= customer.created_at.to_date %> diff --git a/app/views/spree/billing/shared/_main_menu.html.erb b/app/views/spree/billing/shared/_main_menu.html.erb index c4b6cdcdd..df253ddf4 100644 --- a/app/views/spree/billing/shared/_main_menu.html.erb +++ b/app/views/spree/billing/shared/_main_menu.html.erb @@ -23,6 +23,9 @@ + diff --git a/config/locales/en.yml b/config/locales/en.yml index 98ef31afa..c502a4cb3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -234,6 +234,7 @@ en: match_any: "Some line items must from selected age group" match_all: "All line items must from selected age group" billing: + places: "places" code: "code" name: "name" logo: "logo" diff --git a/config/routes.rb b/config/routes.rb index c2b61b362..983e8ceb1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -260,6 +260,7 @@ end resources :adjustments end + resources :places put '/switch_vendor', to: 'base#switch_vendor' get '/forbidden', to: 'errors#forbidden', as: :forbidden root to: redirect('/billing/report') diff --git a/db/migrate/20240424080551_create_cm_customer_taxons.rb b/db/migrate/20240424080551_create_cm_customer_taxons.rb new file mode 100644 index 000000000..0b7fb6917 --- /dev/null +++ b/db/migrate/20240424080551_create_cm_customer_taxons.rb @@ -0,0 +1,12 @@ +class CreateCmCustomerTaxons < ActiveRecord::Migration[7.0] + def change + create_table :cm_customer_taxons do |t| + t.references :customer, null: false, foreign_key: { to_table: :cm_customers } + t.references :taxon, null: false, foreign_key: { to_table: :spree_taxons } + + t.index [:customer_id, :taxon_id], unique: true + + t.timestamps + end + end +end diff --git a/db/migrate/20240425042912_remove_taxon_id_from_cm_customer.rb b/db/migrate/20240425042912_remove_taxon_id_from_cm_customer.rb new file mode 100644 index 000000000..ac6628cdb --- /dev/null +++ b/db/migrate/20240425042912_remove_taxon_id_from_cm_customer.rb @@ -0,0 +1,5 @@ +class RemoveTaxonIdFromCmCustomer < ActiveRecord::Migration[7.0] + def change + remove_column :cm_customers, :taxon_id, :bigint, if_exists: true + end +end diff --git a/db/migrate/20240429080434_add_place_id_to_cm_customer.rb b/db/migrate/20240429080434_add_place_id_to_cm_customer.rb new file mode 100644 index 000000000..2f40821c8 --- /dev/null +++ b/db/migrate/20240429080434_add_place_id_to_cm_customer.rb @@ -0,0 +1,5 @@ +class AddPlaceIdToCmCustomer < ActiveRecord::Migration[7.0] + def change + add_reference :cm_customers, :place, foreign_key: { to_table: :cm_places }, index: true, if_not_exists: true + end +end diff --git a/lib/spree_cm_commissioner/test_helper/factories/customers_taxons_factory.rb b/lib/spree_cm_commissioner/test_helper/factories/customers_taxons_factory.rb new file mode 100644 index 000000000..05cf73508 --- /dev/null +++ b/lib/spree_cm_commissioner/test_helper/factories/customers_taxons_factory.rb @@ -0,0 +1,6 @@ +FactoryBot.define do + factory :cm_customer_taxon, class: SpreeCmCommissioner::CustomerTaxon do + association :customer, factory: :cm_customer + association :taxon, factory: :taxon + end +end diff --git a/spec/models/spree_cm_commissioner/customer_spec.rb b/spec/models/spree_cm_commissioner/customer_spec.rb index 759495034..383cfb47e 100644 --- a/spec/models/spree_cm_commissioner/customer_spec.rb +++ b/spec/models/spree_cm_commissioner/customer_spec.rb @@ -3,47 +3,38 @@ RSpec.describe SpreeCmCommissioner::Customer, type: :model do describe '#callback before_validation' do let!(:vendor1) { create(:cm_vendor_with_product, name: 'Phnom Penh Hotel', code: 'PPH') } - let!(:vendor2) { create(:cm_vendor_with_product, name: 'Siem Reap Hotel') } - let!(:customer1) { create(:cm_customer, vendor: vendor1)} - let!(:customer3) { create(:cm_customer, email: 'panhachom@gmail.com', vendor: vendor2)} + let!(:place1) { create(:cm_place, name: 'KRS') } + let!(:place2) { create(:cm_place, name: 'KSD') } + let!(:place3) { create(:cm_place, name: 'KR') } + let!(:customer1) { create(:cm_customer, place_id: place1.id , vendor: vendor1)} + let!(:customer2) { create(:cm_customer, place_id: place1.id, email: 'panhachom@gmail.com', vendor: vendor1)} context 'create customer number ' do it 'return customer increament by 1' do - customer2 = SpreeCmCommissioner::Customer.create(vendor_id: vendor1.id) - expect(customer1.number).to eq 'PPH-000001' - expect(customer2.number).to eq 'PPH-000002' + customer3 = SpreeCmCommissioner::Customer.create(vendor_id: vendor1.id, place_id: place1.id) + + expect(customer1.number).to eq 'KRS-000001' + expect(customer2.number).to eq 'KRS-000002' + expect(customer3.number).to eq 'KRS-000003' end end - it "change customer number if vendor_code is change" do - vendor10 = Spree::Vendor.create(name: 'PhnomPenh Angkor',code: "PHN") - customer10 = SpreeCmCommissioner::Customer.create!(vendor_id: vendor10.id) - customer20 = SpreeCmCommissioner::Customer.create(vendor_id: vendor10.id) - vendor10.reload - vendor10.update(code: 'PPP') - vendor10.reload - expect(customer10.reload.number).to eq 'PPP-000001' - expect(customer20.reload.number).to eq 'PPP-000002' - vendor10.update(code: 'PPH') - vendor10.reload - expect(customer10.reload.number).to eq 'PPH-000001' - expect(customer20.reload.number).to eq 'PPH-000002' - end + it "change customer number if location is change" do + customer1.update(place_id: place2.id) + customer2.update(place_id: place2.id) - it 'return first 3 letter of vendor_name if vendor_code is nil' do - expect(customer3.number).to eq 'SIE-000001' - end + customer1.update_number + customer2.update_number - it 'return 2 different customer from 2 different vendor' do - expect(customer1.number).to eq 'PPH-000001' - expect(customer3.number).to eq 'SIE-000001' - end + expect(customer1.number).to eq 'KSD-000001' + expect(customer2.number).to eq 'KSD-000002' + end - it 'return 2 different customer from 2 different vendor' do - expect(customer1.number).to eq 'PPH-000001' - expect(customer3.number).to eq 'SIE-000001' - end + it 'return customer number starts from 1 if there is no customer with the same location' do + customer4 = SpreeCmCommissioner::Customer.create(vendor_id: vendor1.id, place_id: place3.id) + expect(customer4.number).to eq 'KR-000001' + end end describe '#subscribable_variants' do @@ -52,34 +43,34 @@ let(:taxon1) { create(:taxon) } let(:taxon2) { create(:taxon) } - let!(:customer1) { create(:cm_customer, taxon_id: taxon1.id, vendor: vendor) } + let!(:place1) { create(:cm_place, name: 'KRS') } + + let!(:customer1) { create(:cm_customer, vendor: vendor, place_id: place1.id) } + let!(:customer2) { create(:cm_customer, vendor: vendor, place_id: place1.id) } - let(:product1) { create(:product, vendor: customer1.vendor,subscribable: true) } + before do + create(:cm_customer_taxon, customer: customer1, taxon: taxon1) + create(:cm_customer_taxon, customer: customer2, taxon: taxon2) - it "return all product's variants that has the same taxon as customer" do - vendor.reload - customer2 = create(:cm_customer, taxon_id: taxon2.id, vendor: vendor) - product2 = create(:product, vendor: customer2.vendor,subscribable: true) + product1 = create(:product, vendor: vendor, subscribable: true) + product2 = create(:product, vendor: vendor, subscribable: true) product1.taxons = [taxon1] product2.taxons = [taxon2] - variant11 = create(:variant, product: product1) - variant12 = create(:variant, product: product1) - variant21 = create(:variant, product: product2) - variant22 = create(:variant, product: product2) + create_list(:variant, 2, product: product1) + create_list(:variant, 2, product: product2) + end + it "returns all product's variants that have the same taxon as the customer" do variants_list1 = customer1.subscribable_variants variants_list2 = customer2.subscribable_variants expect(variants_list1.size).to eq 2 expect(variants_list2.size).to eq 2 - expect(variants_list1).to include(variant11) - expect(variants_list1).to include(variant12) - - expect(variants_list2).to include(variant21) - expect(variants_list2).to include(variant22) + expect(variants_list1).to include(*customer1.variants) + expect(variants_list2).to include(*customer2.variants) end end end \ No newline at end of file From 1c0235f4d5824d3036c63df3319ece6917d48bdf Mon Sep 17 00:00:00 2001 From: tk Date: Mon, 6 May 2024 17:08:12 +0700 Subject: [PATCH 2/3] close #1372 change issued-date from created_at to start_date --- app/views/spree/billing/report/balance_due.html.erb | 2 +- app/views/spree/billing/report/paid.html.erb | 2 +- app/views/spree/billing/report/show.html.erb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/spree/billing/report/balance_due.html.erb b/app/views/spree/billing/report/balance_due.html.erb index 7b0280622..eb841f04a 100644 --- a/app/views/spree/billing/report/balance_due.html.erb +++ b/app/views/spree/billing/report/balance_due.html.erb @@ -50,7 +50,7 @@ <% @orders.each do |order| %> <%= link_to order.invoice&.invoice_number, edit_billing_order_path(order) %> - <%= order.created_at.to_date %> + <%= order.line_items[0].from_date.to_date %> <% if order.customer.first_name.present? %> <%= link_to order.customer.first_name, edit_billing_customer_path(order.customer) %> diff --git a/app/views/spree/billing/report/paid.html.erb b/app/views/spree/billing/report/paid.html.erb index 410fa802b..d10b9382f 100644 --- a/app/views/spree/billing/report/paid.html.erb +++ b/app/views/spree/billing/report/paid.html.erb @@ -38,7 +38,7 @@ <% @orders.each do |order| %> <%= link_to order.invoice&.invoice_number, edit_billing_order_path(order) %> - <%= order.created_at.to_date %> + <%= order.line_items[0].from_date.to_date %> <% if order.customer.first_name.present? %> <%= link_to order.customer.first_name, edit_billing_customer_path(order.customer) %> diff --git a/app/views/spree/billing/report/show.html.erb b/app/views/spree/billing/report/show.html.erb index 4c9163bcf..4f7fb40e9 100644 --- a/app/views/spree/billing/report/show.html.erb +++ b/app/views/spree/billing/report/show.html.erb @@ -27,7 +27,7 @@ <% @orders.each do |order| %> <%= link_to order.invoice&.invoice_number, edit_billing_order_path(order) %> - <%= order.created_at.to_date %> + <%= order.line_items[0].from_date.to_date %> <% if order.customer.first_name.present? %> <%= link_to order.customer.first_name, edit_billing_customer_path(order.customer) %> From 69170cfcba1f4ca4303810680d4b8d5ec4716a78 Mon Sep 17 00:00:00 2001 From: tk Date: Tue, 25 Jun 2024 11:12:02 +0700 Subject: [PATCH 3/3] close #1567 added missing translation --- .../spree/billing/businesses/index.html.erb | 4 +- .../spree/billing/customers/_form.html.erb | 8 ++-- .../spree/billing/customers/index.html.erb | 2 +- .../spree/billing/option_types/index.html.erb | 2 +- .../spree/billing/payments/_list.html.erb | 2 +- app/views/spree/billing/places/index.html.erb | 6 +-- app/views/spree/billing/places/new.html.erb | 2 +- .../billing/shared/sub_menu/_setting.html.erb | 2 +- config/locales/en.yml | 7 ++++ config/locales/km.yml | 39 +++++++++++++++---- 10 files changed, 52 insertions(+), 22 deletions(-) diff --git a/app/views/spree/billing/businesses/index.html.erb b/app/views/spree/billing/businesses/index.html.erb index 66441c746..6bee44dd0 100644 --- a/app/views/spree/billing/businesses/index.html.erb +++ b/app/views/spree/billing/businesses/index.html.erb @@ -1,9 +1,9 @@ <% content_for :page_title do %> - <%= @businesses_taxonomy&.name %> + <%= I18n.t('spree.billing.businesses') %> <% end %> <% content_for :page_actions do %> - <%= button_link_to Spree.t('billing.businesses.add_new_business'), spree.new_billing_business_path(), icon: 'add.svg', class: 'no-wrap btn btn-success align-self-center' %> + <%= button_link_to I18n.t('spree.billing.add_new_business'), spree.new_billing_business_path(), icon: 'add.svg', class: 'no-wrap btn btn-success align-self-center' %> <% end %> diff --git a/app/views/spree/billing/customers/_form.html.erb b/app/views/spree/billing/customers/_form.html.erb index 5b14a316b..ac4b1b529 100644 --- a/app/views/spree/billing/customers/_form.html.erb +++ b/app/views/spree/billing/customers/_form.html.erb @@ -6,17 +6,17 @@ <%= f.error_message_on :email %> <% end %> <%= f.field_container :first_name do %> - <%= f.label :first_name, Spree.t(:business_name) %> + <%= f.label :first_name, Spree.t('billing.business_name') %> <%= f.text_field :first_name, class: 'form-control' %> <%= f.error_message_on :first_name %> <% end %> <%= f.field_container :last_name do %> - <%= f.label :last_name, Spree.t(:owner_name) %> + <%= f.label :last_name, Spree.t('billing.owner_name') %> <%= f.text_field :last_name, class: 'form-control' %> <%= f.error_message_on :last_name %> <% end %> <%= f.field_container :place_id do %> - <%= f.label :place_id, Spree.t(:place) %> + <%= f.label :place_id, Spree.t('billing.places') %> <%= f.collection_select(:place_id, SpreeCmCommissioner::Place.all, :id, :name, { include_blank: true }, { class: 'select2-clear' }) %> <%= f.error_message_on :location %> <% end %> @@ -27,7 +27,7 @@ <% end %> <%= f.hidden_field :vendor_id, value: current_vendor.id %> <%= f.field_container :taxons do %> - <%= f.label :taxon_ids, Spree.t('businesses') %> + <%= f.label :taxon_ids, Spree.t('billing.businesses') %> <%= f.collection_select(:taxon_ids, @businesses, :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', multiple: true })%> <%= f.error_message_on :taxon_ids %> <% end %> diff --git a/app/views/spree/billing/customers/index.html.erb b/app/views/spree/billing/customers/index.html.erb index 9822e95b6..ce45a1f78 100644 --- a/app/views/spree/billing/customers/index.html.erb +++ b/app/views/spree/billing/customers/index.html.erb @@ -59,7 +59,7 @@ <%= sort_link @search, :id, Spree.t(:id), {}, {title:"id_title"} %> - <%= sort_link @search, :full_name, Spree.t(:business_name), {}, {title: 'fullname_title'} %> + <%= sort_link @search, :full_name, I18n.t("spree.billing.business_name"), {}, {title: 'fullname_title'} %> <%= sort_link @search, :full_name, Spree.t(:full_name), {}, {title: 'fullname_title'} %> diff --git a/app/views/spree/billing/option_types/index.html.erb b/app/views/spree/billing/option_types/index.html.erb index d73a7ade5..b140634ba 100644 --- a/app/views/spree/billing/option_types/index.html.erb +++ b/app/views/spree/billing/option_types/index.html.erb @@ -1,5 +1,5 @@ <% content_for :page_title do %> - <%= plural_resource_name(Spree::OptionType) %> + <%= Spree.t('option_type') %> <% end %> <% content_for :page_actions do %> diff --git a/app/views/spree/billing/payments/_list.html.erb b/app/views/spree/billing/payments/_list.html.erb index 068476ad9..81c8caf0f 100644 --- a/app/views/spree/billing/payments/_list.html.erb +++ b/app/views/spree/billing/payments/_list.html.erb @@ -2,7 +2,7 @@ - + diff --git a/app/views/spree/billing/places/index.html.erb b/app/views/spree/billing/places/index.html.erb index 49b4094a4..f00db2734 100644 --- a/app/views/spree/billing/places/index.html.erb +++ b/app/views/spree/billing/places/index.html.erb @@ -3,7 +3,7 @@ <% end %> <% content_for :page_actions do %> - <%= button_link_to Spree.t(:new_place), new_billing_place_path, { class: "btn-success", icon: 'add.svg', id: 'admin_new_place' } %> + <%= button_link_to I18n.t('spree.billing.new_place'), new_billing_place_path, { class: "btn-success", icon: 'add.svg', id: 'admin_new_place' } %> <% end if can?(:create, SpreeCmCommissioner::Place) %> <% content_for :table_filter do %> @@ -37,8 +37,8 @@ - - + + diff --git a/app/views/spree/billing/places/new.html.erb b/app/views/spree/billing/places/new.html.erb index 6ffa18cf5..85b852809 100644 --- a/app/views/spree/billing/places/new.html.erb +++ b/app/views/spree/billing/places/new.html.erb @@ -1,6 +1,6 @@ <% content_for :page_title do %> <%= page_header_back_button spree.billing_places_path %> - <%= Spree.t(:new_place) %> + <%= Spree.t('billing.new_place') %> <% end %>
<%= render partial: 'spree/admin/shared/error_messages', locals: { target: @object } %> diff --git a/app/views/spree/billing/shared/sub_menu/_setting.html.erb b/app/views/spree/billing/shared/sub_menu/_setting.html.erb index a7b5d6209..a9964eb67 100644 --- a/app/views/spree/billing/shared/sub_menu/_setting.html.erb +++ b/app/views/spree/billing/shared/sub_menu/_setting.html.erb @@ -5,5 +5,5 @@ <% if spree_current_user.has_spree_role?('admin') || spree_current_user.permissions.exists?(entry: 'spree/billing/roles') %> <%= configurations_sidebar_menu_item(I18n.t('spree.billing.roles'), billing_roles_url) %> <% end %> - <%= tab :vendor, selected: request.path.include?('/vendors'), url: edit_billing_vendor_url(@current_vendor.id), label: Spree.t('billing.vendor') %> + <%= tab :vendor, selected: request.path.include?('/vendors'), url: edit_billing_vendor_url(@current_vendor.id), label: I18n.t('spree.vendor') %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 918b5a186..472e3aeaf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -241,8 +241,13 @@ en: match_any: "Some line items must from selected age group" match_all: "All line items must from selected age group" billing: + owner_name: "Owner Name" + new_place: "New Place" + payment_date: "Payment Date" new_order: "New Order" businesses: "Businesses" + add_new_business: "Add New Business" + business_name: "Business Name" places: "Places" code: "code" name: "name" @@ -336,6 +341,8 @@ en: show_invoices: "Show Invoices" spree/report: cashier: "Cashier" + spree/payment: + number: "Number" errors: models: spree_cm_commissioner/service_calendar: diff --git a/config/locales/km.yml b/config/locales/km.yml index 82556a13e..45216cad1 100644 --- a/config/locales/km.yml +++ b/config/locales/km.yml @@ -228,12 +228,19 @@ km: match_any: "Some line items must from selected age group" match_all: "All line items must from selected age group" billing: - code: "code" - name: "name" - logo: "logo" - payment_qrcode: "Payment QRCode" - image: "image" - order_line_items: "Order Line Items" + owner_name: "MISSING" + new_place: "MISSING" + new_order: "MISSING" + businesses: "MISSING" + add_new_business: "MISSING" + business_name: "MISSING" + places: "MISSING" + code: "MISSING" + name: "MISSING" + logo: "MISSING" + payment_qrcode: "MISSING" + image: "MISSING" + order_line_items: "MISSING" new_role: "បង្កើតតួនាទីថ្មី" role_id: "កូដតួនាទី" settings: "ការកំណត់" @@ -248,7 +255,11 @@ km: balance_due_orders: "វិក្កយបត្រមិនទាន់បង់" overdue_orders: "វិក្កយបត្រហួសថ្ងៃបង់" orders: "វិក្កយបត្រ" - customers: "អតិថិជន" + customers: + re_create_order: + success: "Invoice Created" + fails: "Invoice for this month is already exist " + customers: "អតិថិជន" roles: "តួនាទី" subscriptions: "ការប្រើប្រាស់" active_subscription: "កំពុងប្រើប្រាស់" @@ -257,7 +268,8 @@ km: users: "គណនីបុគ្គលិក" day: "ថ្ងៃ" products: "ទំនិញ" - vendor: "vendor" + account_name: "MISSING" + account_number: "MISSING" payment_state: paid: "បង់រួច" balance_due: "មិនទាន់បង់" @@ -281,10 +293,16 @@ km: activerecord: attributes: spree/order: + product_type: "MISSING" + customer_name: "MISSING" + issued_date: "MISSING" + payment_date: "MISSING" + printing_date: "MISSING" customer_id: "លេខកូដអតិថិជន" to_date: "រហូតដល់ថ្ងៃ" from_date: "ពីថ្ងៃ" created_at: "បង្កើតនៅថ្ងៃ" + updated_at: "MISSING" start_date: "ថ្ងៃចាប់ផ្តើម" start_date_range: "ចន្លោះថ្ងៃចាប់ផ្តើម" phone_number: "លេខទូរសព្ទ" @@ -295,8 +313,13 @@ km: type: "ប្រភេទ" select_date: "ជ្រើសរើសថ្ងៃ" taxon: "ប្រភេទ" + quantity: "MISSING" + amount: "MISSING" + show_invoices: "MISSING" spree/report: cashier: "អ្នកគិតលុយ" + spree/payment: + number: "MISSING" errors: models: spree_cm_commissioner/service_calendar:
<%= Spree::Payment.human_attribute_name(:number) %><%= I18n.t(:number, scope: 'activerecord.attributes.spree/payment') %> <%= "#{Spree.t('date')}/#{Spree.t('time')}" %> <%= Spree.t(:amount) %> <%= Spree.t(:payment_method) %>
<%= sort_link @search,:name, Spree.t(:name), { default_order: "desc" }, {title: 'admin_places_listing_name_title'} %> <%= sort_link @search,:code, Spree.t(:code), { default_order: "desc" }, {title: 'admin_places_listing_code_title'} %><%= sort_link @search,:updated_at, Spree.t(:updated_at), { default_order: "desc" }, {title: 'admin_places_listing_updated_at_title'} %><%= sort_link @search,:created_at, Spree.t(:created_at), { default_order: "desc" }, {title: 'admin_places_listing_created_at_title'} %><%= sort_link @search,:updated_at, I18n.t(:updated_at, scope: 'activerecord.attributes.spree/order'), { default_order: "desc" }, {title: 'admin_places_listing_updated_at_title'} %><%= sort_link @search,:created_at, I18n.t(:created_at, scope: 'activerecord.attributes.spree/order'), { default_order: "desc" }, {title: 'admin_places_listing_created_at_title'} %>