vyapari 0.1.5dev9 → 0.1.5dev10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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