vyapari 0.1.5dev9 → 0.1.5dev10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/vyapari/store_manager/base_controller.rb +3 -0
  3. data/app/controllers/vyapari/store_manager/dashboard_controller.rb +1 -0
  4. data/app/controllers/vyapari/store_manager/reports/invoices_controller.rb +206 -101
  5. data/app/controllers/vyapari/store_manager/reports/sales_controller.rb +299 -0
  6. data/app/controllers/vyapari/store_manager/reports/stock_controller.rb +1 -1
  7. data/app/controllers/vyapari/terminal_staff/dashboard_controller.rb +2 -1
  8. data/app/models/bank_account.rb +44 -0
  9. data/app/models/brand.rb +8 -13
  10. data/app/models/category.rb +3 -3
  11. data/app/models/contact.rb +72 -0
  12. data/app/models/country.rb +6 -4
  13. data/app/models/exchange_rate.rb +2 -2
  14. data/app/models/invoice.rb +12 -8
  15. data/app/models/line_item.rb +3 -3
  16. data/app/models/product.rb +3 -3
  17. data/app/models/region.rb +11 -17
  18. data/app/models/stock_bundle.rb +4 -4
  19. data/app/models/stock_entry.rb +8 -7
  20. data/app/models/store.rb +52 -21
  21. data/app/models/supplier.rb +19 -25
  22. data/app/models/terminal.rb +3 -3
  23. data/app/models/vyapari/application_record.rb +1 -2
  24. data/app/views/layouts/vyapari/_store_manager_menu.html.erb +24 -5
  25. data/app/views/layouts/vyapari/_terminal_staff_menu.html.erb +6 -3
  26. data/app/views/layouts/vyapari/store_manager.html.erb +4 -4
  27. data/app/views/vyapari/store_manager/dashboard/_sales_counts.html.erb +90 -0
  28. data/app/views/vyapari/store_manager/dashboard/_stock_counts.html.erb +63 -0
  29. data/app/views/vyapari/store_manager/dashboard/_terminals.html.erb +23 -0
  30. data/app/views/vyapari/store_manager/dashboard/index.html.erb +51 -79
  31. data/app/views/vyapari/store_manager/reports/invoices/_index.html.erb +65 -0
  32. data/app/views/vyapari/store_manager/reports/invoices/index.html.erb +105 -0
  33. data/app/views/vyapari/store_manager/reports/sales/_index.html.erb +64 -0
  34. data/app/views/vyapari/store_manager/reports/sales/index.html.erb +105 -0
  35. data/app/views/vyapari/terminal_staff/dashboard/_counts.html.erb +61 -18
  36. data/config/routes.rb +2 -0
  37. data/db/migrate/20170000000203_create_contacts.rb +1 -1
  38. data/db/migrate/20170000000206_create_stores.rb +1 -1
  39. data/lib/vyapari/version.rb +1 -1
  40. metadata +16 -6
@@ -111,7 +111,7 @@ module Vyapari
111
111
  end
112
112
 
113
113
  def set_navs
114
- set_nav("reports/stock")
114
+ set_nav("store_manager/reports")
115
115
  end
116
116
 
117
117
  def render_report
@@ -4,6 +4,7 @@ module Vyapari
4
4
 
5
5
  # GET /dashboard
6
6
  def index
7
+ @date = params[:date] ? Date.parse(params[:date]) : Date.today
7
8
  end
8
9
 
9
10
  def search
@@ -19,7 +20,7 @@ module Vyapari
19
20
  description: "#{@store.name}",
20
21
  links: [
21
22
  {name: "Home", link: user_dashboard_path, icon: 'fa-building-o'},
22
- {name: @terminal.name, link: terminal_staff_dashboard_path(@store), icon: 'fa-desktop'}
23
+ {name: @terminal.name, link: terminal_staff_dashboard_path(@store), icon: 'fa-desktop', active: true}
23
24
  ]
24
25
  }
25
26
  end
@@ -0,0 +1,44 @@
1
+ class BankAccount < Vyapari::ApplicationRecord
2
+
3
+ # Validations
4
+ validates :account_number, presence: true
5
+ #validates :email, length: {maximum: 128}, allow_blank: true
6
+ #validates :phone, length: {maximum: 128}, allow_blank: true
7
+
8
+ # Associations
9
+ belongs_to :bank_accountable, :polymorphic => true
10
+
11
+ # ------------------
12
+ # Class Methods
13
+ # ------------------
14
+
15
+ # return an active record relation object with the search query in its where clause
16
+ # Return the ActiveRecord::Relation object
17
+ # == Examples
18
+ # >>> obj.search(query)
19
+ # => ActiveRecord::Relation object
20
+ scope :search, lambda {|query| joins(:country).where("LOWER(bank_accounts.account_number) LIKE LOWER('%#{query}%') OR
21
+ LOWER(bank_accounts.iban) LIKE LOWER('%#{query}%') OR
22
+ LOWER(bank_accounts.ifsc_swiftcode) LIKE LOWER('%#{query}%') OR
23
+ LOWER(bank_accounts.bank_name) LIKE LOWER('%#{query}%') OR
24
+ LOWER(bank_accounts.city) LIKE LOWER('%#{query}%') OR
25
+ LOWER(countries.name) LIKE LOWER('%#{query}%')
26
+ ")}
27
+
28
+ # ------------------
29
+ # Instance Methods
30
+ # ------------------
31
+
32
+ def display_name
33
+ self.account_number_was
34
+ end
35
+
36
+ def can_be_edited?
37
+ true
38
+ end
39
+
40
+ def can_be_deleted?
41
+ false
42
+ end
43
+
44
+ end
data/app/models/brand.rb CHANGED
@@ -5,15 +5,15 @@ class Brand < Vyapari::ApplicationRecord
5
5
  UNPUBLISHED = "unpublished"
6
6
  REMOVED = "removed"
7
7
 
8
- STATUS_HASH = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
- STATUS_HASH_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
8
+ STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
+ STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
10
10
 
11
11
  FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
12
12
  FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
13
13
 
14
14
  # Validations
15
- validates :name, :presence=> true, uniqueness: true
16
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
15
+ validates :name, :presence=> true, uniqueness: true, length: {minimum: 3, maximum: 250}
16
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
17
17
 
18
18
  # Associations
19
19
  has_one :brand_image, :as => :imageable, :dependent => :destroy, :class_name => "Image::BrandImage"
@@ -32,16 +32,18 @@ class Brand < Vyapari::ApplicationRecord
32
32
  # => ActiveRecord::Relation object
33
33
  scope :search, lambda { |query| where("LOWER(name) LIKE LOWER('%#{query}%')")
34
34
  }
35
-
36
- scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
37
35
  scope :featured, lambda { |val| where(featured: val) }
38
36
 
37
+ scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
39
38
  scope :published, -> { where(status: PUBLISHED) }
40
39
  scope :unpublished, -> { where(status: UNPUBLISHED) }
41
40
  scope :removed, -> { where(status: REMOVED) }
42
41
 
43
42
  scope :this_month, lambda { where("created_at >= ? AND created_at <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
44
43
 
44
+ # Import Methods
45
+ # --------------
46
+
45
47
  def self.save_row_data(row)
46
48
 
47
49
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
@@ -155,13 +157,6 @@ class Brand < Vyapari::ApplicationRecord
155
157
 
156
158
  def can_be_deleted?
157
159
  removed? && self.products.blank?
158
- #if self.jobs.any?
159
- # self.errors.add(:base, DELETE_MESSAGE)
160
- # return false
161
- #else
162
- # return true
163
- #end
164
- #return true
165
160
  end
166
161
 
167
162
  end
@@ -5,8 +5,8 @@ class Category < Vyapari::ApplicationRecord
5
5
  UNPUBLISHED = "unpublished"
6
6
  REMOVED = "removed"
7
7
 
8
- STATUS_HASH = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
- STATUS_HASH_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
8
+ STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
+ STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
10
10
 
11
11
  FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
12
12
  FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
@@ -14,7 +14,7 @@ class Category < Vyapari::ApplicationRecord
14
14
  # Validations
15
15
  validates :name, presence: true, uniqueness: true
16
16
  validates :one_liner, presence: false
17
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
17
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
18
18
 
19
19
  # Associations
20
20
  has_many :products
@@ -0,0 +1,72 @@
1
+ class Contact < Vyapari::ApplicationRecord
2
+
3
+ # Validations
4
+ validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
5
+ validates :email, length: {maximum: 128}, allow_blank: true
6
+ validates :phone, length: {maximum: 128}, allow_blank: true
7
+
8
+ # Associations
9
+ belongs_to :contactable, :polymorphic => true
10
+
11
+ # ------------------
12
+ # Class Methods
13
+ # ------------------
14
+
15
+ # return an active record relation object with the search query in its where clause
16
+ # Return the ActiveRecord::Relation object
17
+ # == Examples
18
+ # >>> obj.search(query)
19
+ # => ActiveRecord::Relation object
20
+ scope :search, lambda {|query| where("LOWER(contacts.name) LIKE LOWER('%#{query}%') OR
21
+ LOWER(contacts.email) LIKE LOWER('%#{query}%') OR
22
+ LOWER(contacts.phone) LIKE LOWER('%#{query}%') OR
23
+ LOWER(contacts.landline) LIKE LOWER('%#{query}%') OR
24
+ LOWER(contacts.fax) LIKE LOWER('%#{query}%') OR
25
+ LOWER(contacts.designation) LIKE LOWER('%#{query}%')
26
+ ")}
27
+
28
+ # Import Methods
29
+ # --------------
30
+
31
+ # TODO - this is yet to be done
32
+ def self.save_row_data(row)
33
+
34
+ row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
35
+
36
+ return if row[:name].blank?
37
+
38
+ country = Contact.find_by_code(row[:code]) || Contact.new
39
+ country.name = row[:name]
40
+ country.code = row[:code]
41
+
42
+ # Initializing error hash for displaying all errors altogether
43
+ error_object = Kuppayam::Importer::ErrorHash.new
44
+
45
+ if country.valid?
46
+ country.save!
47
+ else
48
+ summary = "Error while saving country: #{country.name}"
49
+ details = "Error! #{country.errors.full_messages.to_sentence}"
50
+ error_object.errors << { summary: summary, details: details }
51
+ end
52
+
53
+ return error_object
54
+ end
55
+
56
+ # ------------------
57
+ # Instance Methods
58
+ # ------------------
59
+
60
+ def display_name
61
+ self.name_was
62
+ end
63
+
64
+ def can_be_edited?
65
+ true
66
+ end
67
+
68
+ def can_be_deleted?
69
+ false
70
+ end
71
+
72
+ end
@@ -1,8 +1,8 @@
1
1
  class Country < Vyapari::ApplicationRecord
2
2
 
3
3
  # Validations
4
- validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
5
- validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 32}, allow_blank: false
4
+ validates :name, presence: true, length: {minimum: 2, maximum: 128}, allow_blank: false
5
+ validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 16}, allow_blank: false
6
6
 
7
7
  # Associations
8
8
  has_many :regions
@@ -19,6 +19,9 @@ class Country < Vyapari::ApplicationRecord
19
19
  # => ActiveRecord::Relation object
20
20
  scope :search, lambda {|query| where("LOWER(countries.name) LIKE LOWER('%#{query}%')")}
21
21
 
22
+ # Import Methods
23
+ # --------------
24
+
22
25
  def self.save_row_data(row)
23
26
 
24
27
  row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
@@ -56,8 +59,7 @@ class Country < Vyapari::ApplicationRecord
56
59
  end
57
60
 
58
61
  def can_be_deleted?
59
- if self.regions.any?
60
- #self.errors.add(:base, DELETE_MESSAGE)
62
+ if self.regions.any? || self.stores.any?
61
63
  return false
62
64
  else
63
65
  return true
@@ -3,7 +3,7 @@ class ExchangeRate < Vyapari::ApplicationRecord
3
3
  # Validations
4
4
  validates :base_currency, presence: true, length: {minimum: 2, maximum: 6}, allow_blank: false
5
5
  validates :counter_currency, presence: true, length: {minimum: 2, maximum: 6}, allow_blank: false
6
- validates :value, presence: true
6
+ validates :value, presence: true, numericality: { greater_than: 0 }
7
7
  validates :effective_date, presence: true
8
8
 
9
9
  # ------------------
@@ -15,7 +15,7 @@ class ExchangeRate < Vyapari::ApplicationRecord
15
15
  # == Examples
16
16
  # >>> obj.search(query)
17
17
  # => ActiveRecord::Relation object
18
- scope :search, lambda {|query| where("LOWER(base_currency) LIKE LOWER('%#{query}%') OR LOWER(counter_currency) LIKE LOWER('%#{query}%')")}
18
+ scope :search, lambda {|query| where("LOWER(exchange_rates.base_currency) LIKE LOWER('%#{query}%') OR LOWER(exchange_rates.counter_currency) LIKE LOWER('%#{query}%')")}
19
19
 
20
20
  def self.save_row_data(row)
21
21
 
@@ -10,8 +10,11 @@ class Invoice < Vyapari::ApplicationRecord
10
10
  CREDIT_CARD = "credit_card"
11
11
  CHEQUE = "cheque"
12
12
 
13
- STATUS_HASH = {"Draft" => DRAFT, "Active" => ACTIVE, "Cancelled" => CANCELLED}
14
- STATUS_HASH_REVERSE = {DRAFT => "Draft", ACTIVE => "Active", CANCELLED => "Cancelled"}
13
+ STATUS = {"Draft" => DRAFT, "Active" => ACTIVE, "Cancelled" => CANCELLED}
14
+ STATUS_REVERSE = {DRAFT => "Draft", ACTIVE => "Active", CANCELLED => "Cancelled"}
15
+
16
+ PAYMENT_METHOD = {"Cash" => CASH, "Credit" => CREDIT, "Credit Card" => CREDIT_CARD, "Cheque" => CHEQUE}
17
+ PAYMENT_METHOD_REVERSE = {CASH => "Cash", CREDIT => "Credid", CREDIT_CARD => "Credit Card", CHEQUE => "Cheque"}
15
18
 
16
19
  # Call backs
17
20
  before_save :calculate_gross_total_amount
@@ -20,7 +23,7 @@ class Invoice < Vyapari::ApplicationRecord
20
23
  validates :invoice_number, :presence=> true
21
24
  validates :invoice_date, :presence=> true
22
25
 
23
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
26
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
24
27
 
25
28
  # Associations
26
29
  belongs_to :terminal
@@ -40,7 +43,7 @@ class Invoice < Vyapari::ApplicationRecord
40
43
  # == Examples
41
44
  # >>> invoice.search(query)
42
45
  # => ActiveRecord::Relation object
43
- scope :search, lambda { |query| where("LOWER(invoice_number) LIKE LOWER('%#{query}%') OR LOWER(customer_name) LIKE LOWER('%#{query}%') OR LOWER(customer_address) LIKE LOWER('%#{query}%')")
46
+ scope :search, lambda { |query| where("LOWER(invoice_number) LIKE LOWER('%#{query}%') OR LOWER(notes) LIKE LOWER('%#{query}%') OR LOWER(credit_card_number) LIKE LOWER('%#{query}%') OR LOWER(cheque_number) LIKE LOWER('%#{query}%') OR LOWER(customer_name) LIKE LOWER('%#{query}%') OR LOWER(customer_address) LIKE LOWER('%#{query}%') OR LOWER(net_total_amount) LIKE LOWER('%#{query}%')")
44
47
  }
45
48
 
46
49
  scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
@@ -54,10 +57,11 @@ class Invoice < Vyapari::ApplicationRecord
54
57
  scope :credit_card_invoices, -> { where(payment_method: CREDIT_CARD) }
55
58
  scope :cheque_invoices, -> { where(payment_method: CHEQUE) }
56
59
 
57
- scope :payment_method, lambda { |pm| where("LOWER(payment_method)='#{payment_method}'") }
60
+ scope :payment_method, lambda { |pm| where("LOWER(payment_method)=?", ) }
58
61
 
59
- scope :this_month, lambda { where("created_at >= ? AND created_at <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
60
- scope :today, lambda { where('DATE(created_at) = ?', Date.current.in_time_zone)}
62
+ scope :this_month, lambda { where("invoice_date >= ? AND invoice_date <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
63
+ scope :today, lambda { where('DATE(invoice_date) = ?', Date.current.in_time_zone)}
64
+ scope :dated, lambda { |d| where('DATE(invoice_date) = ?', d)}
61
65
 
62
66
  # ------------------
63
67
  # Instance Methods
@@ -78,7 +82,7 @@ class Invoice < Vyapari::ApplicationRecord
78
82
  end
79
83
 
80
84
  def display_status
81
- STATUS_HASH_REVERSE[self.status]
85
+ STATUS_REVERSE[self.status]
82
86
  end
83
87
 
84
88
  def display_payment_method
@@ -7,8 +7,8 @@ class LineItem < Vyapari::ApplicationRecord
7
7
  RETURNED = "returned"
8
8
  CANCELLED = "cancelled"
9
9
 
10
- STATUS_HASH = {"Draft" => DRAFT, "Sold" => SOLD, "Damaged" => DAMAGED, "Returned" => RETURNED, "Cancelled" => CANCELLED}
11
- STATUS_HASH_REVERSE = {DRAFT => "Draft", SOLD => "Sold", DAMAGED => "Damaged", RETURNED => "Returned", CANCELLED => "Cancelled"}
10
+ STATUS = {"Draft" => DRAFT, "Sold" => SOLD, "Damaged" => DAMAGED, "Returned" => RETURNED, "Cancelled" => CANCELLED}
11
+ STATUS_REVERSE = {DRAFT => "Draft", SOLD => "Sold", DAMAGED => "Damaged", RETURNED => "Returned", CANCELLED => "Cancelled"}
12
12
 
13
13
  # Call backs
14
14
  before_save :calculate_total_amount
@@ -18,7 +18,7 @@ class LineItem < Vyapari::ApplicationRecord
18
18
  validates :quantity, :presence=> true
19
19
  validates :rate, :presence=> true
20
20
 
21
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
21
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
22
22
 
23
23
  # Associations
24
24
  belongs_to :product, optional: true
@@ -5,8 +5,8 @@ class Product < Vyapari::ApplicationRecord
5
5
  UNPUBLISHED = "unpublished"
6
6
  REMOVED = "removed"
7
7
 
8
- STATUS_HASH = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
- STATUS_HASH_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
8
+ STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
9
+ STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
10
10
 
11
11
  FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
12
12
  FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
@@ -19,7 +19,7 @@ class Product < Vyapari::ApplicationRecord
19
19
  validates :ean_sku, presence: true
20
20
 
21
21
  #validates :description, presence: true
22
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
22
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
23
23
 
24
24
  # Associations
25
25
  has_one :product_image, :as => :imageable, :dependent => :destroy, :class_name => "Image::ProductImage"
data/app/models/region.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  class Region < Vyapari::ApplicationRecord
2
2
 
3
3
  # Validations
4
- validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
5
- validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 32}, allow_blank: false
4
+ validates :name, presence: true, length: {minimum: 2, maximum: 128}, allow_blank: false
5
+ validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 16}, allow_blank: false
6
6
  validates :country, presence: true
7
7
 
8
8
  # Associations
@@ -18,7 +18,10 @@ class Region < Vyapari::ApplicationRecord
18
18
  # == Examples
19
19
  # >>> obj.search(query)
20
20
  # => ActiveRecord::Relation object
21
- scope :search, lambda {|query| joins(:country).where("LOWER(cities.name) LIKE LOWER('%#{query}%') OR LOWER(countries.name) LIKE LOWER('%#{query}%')")}
21
+ scope :search, lambda {|query| joins(:country).where("LOWER(regions.name) LIKE LOWER('%#{query}%') OR LOWER(countries.name) LIKE LOWER('%#{query}%')")}
22
+
23
+ # Import Methods
24
+ # --------------
22
25
 
23
26
  def self.save_row_data(row)
24
27
 
@@ -62,20 +65,11 @@ class Region < Vyapari::ApplicationRecord
62
65
  end
63
66
 
64
67
  def can_be_deleted?
65
- # if self.stores.any?
66
- # self.errors.add(:base, DELETE_MESSAGE)
67
- # return false
68
- # else
69
- # return true
70
- # end
71
- return true
72
- end
73
-
74
- def report_heading
75
- rh = []
76
- rh << self.company.try(:name) if self.company.name
77
- rh << self.display_name
78
- rh.join(", ")
68
+ if self.stores.any?
69
+ return false
70
+ else
71
+ return true
72
+ end
79
73
  end
80
74
 
81
75
  end
@@ -7,13 +7,13 @@ class StockBundle < ActiveRecord::Base
7
7
  ERRORED = "errored"
8
8
  APPROVED = "approved"
9
9
 
10
- STATUS_HASH = {"Pending" => PENDING, "Approved" => APPROVED, "Errored" => ERRORED}
11
- STATUS_HASH_REVERSE = {PENDING => "Pending", APPROVED => "Approved", ERRORED => "Errored"}
10
+ STATUS = {"Pending" => PENDING, "Approved" => APPROVED, "Errored" => ERRORED}
11
+ STATUS_REVERSE = {PENDING => "Pending", APPROVED => "Approved", ERRORED => "Errored"}
12
12
 
13
13
  # Validations
14
14
  validates :name, :presence=> true, uniqueness: true
15
15
  validates :uploaded_date, presence: true
16
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
16
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
17
17
  # validates :file, :presence=> true
18
18
 
19
19
  # Associations
@@ -163,7 +163,7 @@ class StockBundle < ActiveRecord::Base
163
163
  end
164
164
 
165
165
  def display_status
166
- STATUS_HASH_REVERSE[self.status]
166
+ STATUS_REVERSE[self.status]
167
167
  end
168
168
 
169
169
  def display_file_name
@@ -9,14 +9,14 @@ class StockEntry < Vyapari::ApplicationRecord
9
9
  RESERVED = "reserved"
10
10
  PENDING = "pending"
11
11
 
12
- STATUS_HASH = {"Active" => ACTIVE, "Sold" => SOLD, "Damaged" => DAMAGED, "Received" => RECEIVED, "Reserved" => RESERVED, "Pending" => PENDING, "Returned" => RETURNED}
13
- STATUS_HASH_REVERSE = {ACTIVE => "Active", SOLD => "Sold", DAMAGED => "Damaged", RECEIVED => "Received", RESERVED => "Reserved", PENDING => "Pending", RETURNED => "Returned"}
12
+ STATUS = {"Active" => ACTIVE, "Sold" => SOLD, "Damaged" => DAMAGED, "Received" => RECEIVED, "Reserved" => RESERVED, "Pending" => PENDING, "Returned" => RETURNED}
13
+ STATUS_REVERSE = {ACTIVE => "Active", SOLD => "Sold", DAMAGED => "Damaged", RECEIVED => "Received", RESERVED => "Reserved", PENDING => "Pending", RETURNED => "Returned"}
14
14
 
15
15
  # Validations
16
16
  validates :store, presence: true
17
17
  validates :product, presence: true
18
18
  validates :quantity, presence: true, numericality: true
19
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
19
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
20
20
 
21
21
  # Associations
22
22
  belongs_to :store
@@ -50,8 +50,9 @@ class StockEntry < Vyapari::ApplicationRecord
50
50
  scope :reserved, -> { where(status: RESERVED) }
51
51
  scope :in_stock, -> { where(status: [ACTIVE, RECEIVED, RETURNED]) }
52
52
 
53
- scope :this_month, lambda { where("created_at >= ? AND created_at <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
54
- scope :today, lambda { where('DATE(created_at) = ?', Date.current.in_time_zone)}
53
+ scope :this_month, lambda { joins(:invoice).where("invoices.invoice_date >= ? AND invoices.invoice_date <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
54
+ scope :today, lambda { joins(:invoice).where('DATE(invoices.invoice_date) = ?', Date.current.in_time_zone)}
55
+ scope :dated, lambda { |d| joins(:invoice).where('DATE(invoices.invoice_date) = ?', d)}
55
56
 
56
57
  def self.save_row_data(row)
57
58
 
@@ -112,11 +113,11 @@ class StockEntry < Vyapari::ApplicationRecord
112
113
  end
113
114
 
114
115
  def display_store_type
115
- STATUS_HASH[self.status]
116
+ STATUS[self.status]
116
117
  end
117
118
 
118
119
  def display_status
119
- STATUS_HASH_REVERSE[self.status]
120
+ STATUS_REVERSE[self.status]
120
121
  end
121
122
 
122
123
  def slug
data/app/models/store.rb CHANGED
@@ -5,8 +5,8 @@ class Store < Vyapari::ApplicationRecord
5
5
  INACTIVE = "inactive"
6
6
  CLOSED = "closed"
7
7
 
8
- STATUS_HASH = {"Active" => ACTIVE, "Inactive" => INACTIVE, "Closed" => CLOSED}
9
- STATUS_HASH_REVERSE = {ACTIVE => "Active", INACTIVE => "Inactive", CLOSED => "Closed"}
8
+ STATUS = {"Active" => ACTIVE, "Inactive" => INACTIVE, "Closed" => CLOSED}
9
+ STATUS_REVERSE = {ACTIVE => "Active", INACTIVE => "Inactive", CLOSED => "Closed"}
10
10
 
11
11
  # Constants
12
12
  WAREHOUSE = "warehouse"
@@ -26,15 +26,18 @@ class Store < Vyapari::ApplicationRecord
26
26
  validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
27
27
  validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 24}, allow_blank: false
28
28
  validates :store_type, :presence => true, :inclusion => {:in => STORE_TYPES.keys, :presence_of => :store_type, :message => "%{value} is not a valid store type" }
29
- validates :status, :presence=> true, :inclusion => {:in => STATUS_HASH_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
29
+ validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
30
30
 
31
31
  # Associations
32
32
  belongs_to :region, optional: true
33
33
  belongs_to :country, optional: true
34
34
 
35
35
  has_many :terminals
36
+ has_many :invoices
36
37
  has_many :stock_entries
37
38
  has_many :stock_bundles
39
+ has_many :products, through: :stock_entries
40
+
38
41
 
39
42
  # ------------------
40
43
  # Class Methods
@@ -131,6 +134,33 @@ class Store < Vyapari::ApplicationRecord
131
134
  true
132
135
  end
133
136
 
137
+ # Total Counts
138
+
139
+ def total_quantity_of_products_in_stock
140
+ self.stock_entries.active.sum(:quantity) - self.stock_entries.sold.sum(:quantity)
141
+ end
142
+
143
+ def total_no_of_products_in_stock
144
+ self.stock_entries.active.count
145
+ # - self.stock_entries.sold.count
146
+ # self.stock_entries.active.count - self.stock_entries.sold.count
147
+ #begin
148
+ # result = Product.select("COUNT(products.id) as id, MAX(se.store_id) as store_id").
149
+ # joins("LEFT JOIN stock_entries se ON se.product_id = products.id").
150
+ # where("se.store_id = ?", self.id).
151
+ # group("products.id")
152
+ # return result.size.to_i
153
+ #rescue
154
+ #0
155
+ #end
156
+ end
157
+
158
+ # Sold Items Count
159
+
160
+ def sold_items_count(date=Date.today)
161
+ self.stock_entries.dated(date).sold.sum(:quantity)
162
+ end
163
+
134
164
  def sold_items_count_for_today
135
165
  self.stock_entries.today.sold.sum(:quantity)
136
166
  end
@@ -139,6 +169,12 @@ class Store < Vyapari::ApplicationRecord
139
169
  self.stock_entries.this_month.sold.sum(:quantity)
140
170
  end
141
171
 
172
+ # Damaged Items Count
173
+
174
+ def damaged_items_count(date=Date.today)
175
+ self.stock_entries.dated(date).damaged.sum(:quantity)
176
+ end
177
+
142
178
  def damaged_items_count_for_today
143
179
  self.stock_entries.today.damaged.sum(:quantity)
144
180
  end
@@ -147,6 +183,12 @@ class Store < Vyapari::ApplicationRecord
147
183
  self.stock_entries.this_month.damaged.sum(:quantity)
148
184
  end
149
185
 
186
+ # Returned Items Count
187
+
188
+ def returned_items_count(date=Date.today)
189
+ self.stock_entries.dated(date).returned.sum(:quantity)
190
+ end
191
+
150
192
  def returned_items_count_for_today
151
193
  self.stock_entries.today.returned.sum(:quantity)
152
194
  end
@@ -155,6 +197,12 @@ class Store < Vyapari::ApplicationRecord
155
197
  self.stock_entries.this_month.returned.sum(:quantity)
156
198
  end
157
199
 
200
+ # Reserved Items Count
201
+
202
+ def reserved_items_count(date=Date.today)
203
+ self.stock_entries.dated(date).reserved.sum(:quantity)
204
+ end
205
+
158
206
  def reserved_items_count_for_today
159
207
  self.stock_entries.today.reserved.sum(:quantity)
160
208
  end
@@ -163,24 +211,7 @@ class Store < Vyapari::ApplicationRecord
163
211
  self.stock_entries.this_month.reserved.sum(:quantity)
164
212
  end
165
213
 
166
- def in_stock_items_count_as_of_now
167
- self.stock_entries.active.sum(:quantity) - self.stock_entries.sold.sum(:quantity)
168
- end
169
-
170
- def total_no_of_products_in_stock
171
- self.stock_entries.active.count
172
- # - self.stock_entries.sold.count
173
- # self.stock_entries.active.count - self.stock_entries.sold.count
174
- #begin
175
- # result = Product.select("COUNT(products.id) as id, MAX(se.store_id) as store_id").
176
- # joins("LEFT JOIN stock_entries se ON se.product_id = products.id").
177
- # where("se.store_id = ?", self.id).
178
- # group("products.id")
179
- # return result.size.to_i
180
- #rescue
181
- #0
182
- #end
183
- end
214
+
184
215
 
185
216
 
186
217