diff --git a/app/controllers/api/products_controller.rb b/app/controllers/api/products_controller.rb index ca15bfafb..2c5835f66 100644 --- a/app/controllers/api/products_controller.rb +++ b/app/controllers/api/products_controller.rb @@ -53,6 +53,7 @@ class API::ProductsController < API::ApiController :low_stock_alert, :low_stock_threshold, machine_ids: [], product_files_attributes: %i[id attachment _destroy], - product_images_attributes: %i[id attachment is_main _destroy]) + product_images_attributes: %i[id attachment is_main _destroy], + product_stock_movements_attributes: %i[id quantity reason stock_type _destroy]) end end diff --git a/app/frontend/src/javascript/models/product.ts b/app/frontend/src/javascript/models/product.ts index 57aa51809..fc951c1e5 100644 --- a/app/frontend/src/javascript/models/product.ts +++ b/app/frontend/src/javascript/models/product.ts @@ -1,3 +1,5 @@ +import { TDateISO } from '../typings/date-iso'; + export enum StockType { internal = 'internal', external = 'external' @@ -38,5 +40,14 @@ export interface Product { attachment_url?: string, _destroy?: boolean, is_main?: boolean - }> + }>, + product_stock_movements_attributes: Array<{ + id?: number, + quantity?: number, + reason?: string, + stock_type?: string, + remaining_stock?: number, + date?: TDateISO, + _destroy?: boolean + }>, } diff --git a/app/models/product.rb b/app/models/product.rb index 7bc4087a7..946a3c454 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -12,7 +12,10 @@ class Product < ApplicationRecord has_many :product_images, as: :viewable, dependent: :destroy accepts_nested_attributes_for :product_images, allow_destroy: true, reject_if: :all_blank - validates_numericality_of :amount, greater_than: 0, allow_nil: true + has_many :product_stock_movements, dependent: :destroy + accepts_nested_attributes_for :product_stock_movements, allow_destroy: true, reject_if: :all_blank + + validates :amount, numericality: { greater_than: 0, allow_nil: true } scope :active, -> { where(is_active: true) } end diff --git a/app/models/product_stock_movement.rb b/app/models/product_stock_movement.rb new file mode 100644 index 000000000..6d5623f2f --- /dev/null +++ b/app/models/product_stock_movement.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# ProductStockMovement is a model for record the movements of product's stock +class ProductStockMovement < ApplicationRecord + belongs_to :product + + ALL_STOCK_TYPES = %w[internal external].freeze + enum stock_type: ALL_STOCK_TYPES.zip(ALL_STOCK_TYPES).to_h + + ALL_REASONS = %w[incoming_stock returned_by_customer cancelled_by_customer sold missing_from_inventory damaged].freeze + enum reason: ALL_REASONS.zip(ALL_REASONS).to_h + + validates :stock_type, presence: true + validates :stock_type, inclusion: { in: ALL_STOCK_TYPES } + + validates :reason, presence: true + validates :reason, inclusion: { in: ALL_REASONS } +end diff --git a/app/views/api/products/_product.json.jbuilder b/app/views/api/products/_product.json.jbuilder index 37d9fca9b..a6fe177cf 100644 --- a/app/views/api/products/_product.json.jbuilder +++ b/app/views/api/products/_product.json.jbuilder @@ -14,3 +14,11 @@ json.product_images_attributes product.product_images do |f| json.attachment_url f.attachment_url json.is_main f.is_main end +json.product_stock_movements_attributes product.product_stock_movements do |s| + json.id s.id + json.quantity s.quantity + json.reason s.reason + json.stock_type s.stock_type + json.remaining_stock s.remaining_stock + json.date s.date +end diff --git a/db/migrate/20220805083431_create_product_stock_movements.rb b/db/migrate/20220805083431_create_product_stock_movements.rb new file mode 100644 index 000000000..d7c7af564 --- /dev/null +++ b/db/migrate/20220805083431_create_product_stock_movements.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class CreateProductStockMovements < ActiveRecord::Migration[5.2] + def change + create_table :product_stock_movements do |t| + t.belongs_to :product, foreign_key: true + t.integer :quantity + t.string :reason + t.string :stock_type + t.integer :remaining_stock + t.datetime :date + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 864a474d7..ca31162a3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_08_03_091913) do +ActiveRecord::Schema.define(version: 2022_08_05_083431) do # These are extensions that must be enabled in order to support this database enable_extension "fuzzystrmatch" @@ -597,6 +597,18 @@ ActiveRecord::Schema.define(version: 2022_08_03_091913) do t.index ["parent_id"], name: "index_product_categories_on_parent_id" end + create_table "product_stock_movements", force: :cascade do |t| + t.bigint "product_id" + t.integer "quantity" + t.string "reason" + t.string "stock_type" + t.integer "remaining_stock" + t.datetime "date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["product_id"], name: "index_product_stock_movements_on_product_id" + end + create_table "products", force: :cascade do |t| t.string "name" t.string "slug" @@ -1135,6 +1147,7 @@ ActiveRecord::Schema.define(version: 2022_08_03_091913) do add_foreign_key "prepaid_packs", "groups" add_foreign_key "prices", "groups" add_foreign_key "prices", "plans" + add_foreign_key "product_stock_movements", "products" add_foreign_key "products", "product_categories" add_foreign_key "project_steps", "projects" add_foreign_key "project_users", "projects"