GWM : brand removed , gst added in hs code , type added in item category , po type removed in purchase order
This commit is contained in:
parent
75f1758c01
commit
e0e3077019
@ -9,127 +9,127 @@ datasource db {
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
model asset_attachments {
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
attachment_type String @default("DOCUMENT") @db.VarChar(50)
|
||||
file_name String @db.VarChar(255)
|
||||
file_path String @db.VarChar(500)
|
||||
file_type String? @db.VarChar(100)
|
||||
file_size Int?
|
||||
uploaded_by BigInt?
|
||||
amc_contract_id BigInt?
|
||||
service_visit_id BigInt?
|
||||
insurance_id BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
asset_amc_contracts asset_amc_contracts? @relation(fields: [amc_contract_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
attachment_type String @default("DOCUMENT") @db.VarChar(50)
|
||||
file_name String @db.VarChar(255)
|
||||
file_path String @db.VarChar(500)
|
||||
file_type String? @db.VarChar(100)
|
||||
file_size Int?
|
||||
uploaded_by BigInt?
|
||||
amc_contract_id BigInt?
|
||||
service_visit_id BigInt?
|
||||
insurance_id BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
asset_amc_contracts asset_amc_contracts? @relation(fields: [amc_contract_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
asset_insurance_policies asset_insurance_policies? @relation(fields: [insurance_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
asset_service_visits asset_service_visits? @relation(fields: [service_visit_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users users? @relation(fields: [uploaded_by], references: [id], onUpdate: NoAction)
|
||||
asset_service_visits asset_service_visits? @relation(fields: [service_visit_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users users? @relation(fields: [uploaded_by], references: [id], onUpdate: NoAction)
|
||||
}
|
||||
|
||||
model asset_amc_contracts {
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
vendor_id BigInt
|
||||
contract_no String? @db.VarChar(100)
|
||||
contract_type String @default("COMPREHENSIVE") @db.VarChar(30)
|
||||
start_date DateTime @db.Date
|
||||
end_date DateTime @db.Date
|
||||
renewal_date DateTime? @db.Date
|
||||
annual_cost Decimal @default(0) @db.Decimal(12, 2)
|
||||
payment_frequency String @default("ANNUAL") @db.VarChar(20)
|
||||
service_frequency String? @db.VarChar(20)
|
||||
visits_per_year Int?
|
||||
contact_person String? @db.VarChar(150)
|
||||
contact_phone String? @db.VarChar(15)
|
||||
contact_email String? @db.VarChar(150)
|
||||
scope_of_work String?
|
||||
exclusions String?
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_amc_contracts_created_byTousers users? @relation("asset_amc_contracts_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_amc_contracts_updated_byTousers users? @relation("asset_amc_contracts_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
asset_service_visits asset_service_visits[]
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
vendor_id BigInt
|
||||
contract_no String? @db.VarChar(100)
|
||||
contract_type String @default("COMPREHENSIVE") @db.VarChar(30)
|
||||
start_date DateTime @db.Date
|
||||
end_date DateTime @db.Date
|
||||
renewal_date DateTime? @db.Date
|
||||
annual_cost Decimal @default(0) @db.Decimal(12, 2)
|
||||
payment_frequency String @default("ANNUAL") @db.VarChar(20)
|
||||
service_frequency String? @db.VarChar(20)
|
||||
visits_per_year Int?
|
||||
contact_person String? @db.VarChar(150)
|
||||
contact_phone String? @db.VarChar(15)
|
||||
contact_email String? @db.VarChar(150)
|
||||
scope_of_work String?
|
||||
exclusions String?
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_amc_contracts_created_byTousers users? @relation("asset_amc_contracts_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_amc_contracts_updated_byTousers users? @relation("asset_amc_contracts_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
asset_service_visits asset_service_visits[]
|
||||
|
||||
@@index([asset_id], map: "idx_amc_asset_id")
|
||||
@@index([vendor_id], map: "idx_amc_vendor_id")
|
||||
}
|
||||
|
||||
model asset_insurance_policies {
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
policy_no String @db.VarChar(100)
|
||||
insurer_name String @db.VarChar(200)
|
||||
insurer_branch String? @db.VarChar(150)
|
||||
insurer_contact String? @db.VarChar(150)
|
||||
insurer_phone String? @db.VarChar(15)
|
||||
insurer_email String? @db.VarChar(150)
|
||||
policy_type String @default("FIRE_AND_ALLIED") @db.VarChar(50)
|
||||
sum_insured Decimal @default(0) @db.Decimal(15, 2)
|
||||
annual_premium Decimal @default(0) @db.Decimal(12, 2)
|
||||
policy_start_date DateTime @db.Date
|
||||
policy_end_date DateTime @db.Date
|
||||
renewal_date DateTime? @db.Date
|
||||
is_auto_renewal Boolean @default(false)
|
||||
premium_paid Boolean @default(false)
|
||||
premium_paid_date DateTime? @db.Date
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_insurance_policies_created_byTousers users? @relation("asset_insurance_policies_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_insurance_policies_updated_byTousers users? @relation("asset_insurance_policies_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
policy_no String @db.VarChar(100)
|
||||
insurer_name String @db.VarChar(200)
|
||||
insurer_branch String? @db.VarChar(150)
|
||||
insurer_contact String? @db.VarChar(150)
|
||||
insurer_phone String? @db.VarChar(15)
|
||||
insurer_email String? @db.VarChar(150)
|
||||
policy_type String @default("FIRE_AND_ALLIED") @db.VarChar(50)
|
||||
sum_insured Decimal @default(0) @db.Decimal(15, 2)
|
||||
annual_premium Decimal @default(0) @db.Decimal(12, 2)
|
||||
policy_start_date DateTime @db.Date
|
||||
policy_end_date DateTime @db.Date
|
||||
renewal_date DateTime? @db.Date
|
||||
is_auto_renewal Boolean @default(false)
|
||||
premium_paid Boolean @default(false)
|
||||
premium_paid_date DateTime? @db.Date
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_insurance_policies_created_byTousers users? @relation("asset_insurance_policies_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_insurance_policies_updated_byTousers users? @relation("asset_insurance_policies_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
|
||||
@@index([asset_id], map: "idx_insurance_asset_id")
|
||||
}
|
||||
|
||||
model asset_service_visits {
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
amc_contract_id BigInt?
|
||||
visit_type String @db.VarChar(30)
|
||||
visit_date DateTime @db.Date
|
||||
visit_number Int?
|
||||
complaint_no String? @db.VarChar(50)
|
||||
complaint_date DateTime? @db.Date
|
||||
complaint_desc String?
|
||||
engineer_name String? @db.VarChar(150)
|
||||
engineer_phone String? @db.VarChar(15)
|
||||
vendor_id BigInt?
|
||||
work_done String?
|
||||
parts_replaced String?
|
||||
next_service_date DateTime? @db.Date
|
||||
status String @default("COMPLETED") @db.VarChar(20)
|
||||
downtime_hours Decimal? @default(0) @db.Decimal(6, 2)
|
||||
service_cost Decimal? @default(0) @db.Decimal(12, 2)
|
||||
is_under_amc Boolean @default(false)
|
||||
asset_condition_after String? @db.VarChar(20)
|
||||
remarks String?
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
asset_amc_contracts asset_amc_contracts? @relation(fields: [amc_contract_id], references: [id], onUpdate: NoAction)
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_service_visits_created_byTousers users? @relation("asset_service_visits_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_service_visits_updated_byTousers users? @relation("asset_service_visits_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors? @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_id BigInt
|
||||
amc_contract_id BigInt?
|
||||
visit_type String @db.VarChar(30)
|
||||
visit_date DateTime @db.Date
|
||||
visit_number Int?
|
||||
complaint_no String? @db.VarChar(50)
|
||||
complaint_date DateTime? @db.Date
|
||||
complaint_desc String?
|
||||
engineer_name String? @db.VarChar(150)
|
||||
engineer_phone String? @db.VarChar(15)
|
||||
vendor_id BigInt?
|
||||
work_done String?
|
||||
parts_replaced String?
|
||||
next_service_date DateTime? @db.Date
|
||||
status String @default("COMPLETED") @db.VarChar(20)
|
||||
downtime_hours Decimal? @default(0) @db.Decimal(6, 2)
|
||||
service_cost Decimal? @default(0) @db.Decimal(12, 2)
|
||||
is_under_amc Boolean @default(false)
|
||||
asset_condition_after String? @db.VarChar(20)
|
||||
remarks String?
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
asset_amc_contracts asset_amc_contracts? @relation(fields: [amc_contract_id], references: [id], onUpdate: NoAction)
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
users_asset_service_visits_created_byTousers users? @relation("asset_service_visits_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_asset_service_visits_updated_byTousers users? @relation("asset_service_visits_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors? @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
|
||||
@@index([asset_id], map: "idx_service_asset_id")
|
||||
@@index([amc_contract_id], map: "idx_service_amc_id")
|
||||
@ -153,13 +153,13 @@ model asset_transfers {
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
assets assets @relation(fields: [asset_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
departments_asset_transfers_from_department_idTodepartments departments? @relation("asset_transfers_from_department_idTodepartments", fields: [from_department_id], references: [id], onUpdate: NoAction)
|
||||
from_plant locations? @relation("TransferFromPlant", fields: [from_plant_id], references: [id], onUpdate: NoAction)
|
||||
from_plant locations? @relation("TransferFromPlant", fields: [from_plant_id], references: [id], onUpdate: NoAction)
|
||||
users_asset_transfers_from_user_idTousers users? @relation("asset_transfers_from_user_idTousers", fields: [from_user_id], references: [id], onUpdate: NoAction)
|
||||
from_warehouse locations? @relation("TransferFromWarehouse", fields: [from_warehouse_id], references: [id], onUpdate: NoAction)
|
||||
from_warehouse locations? @relation("TransferFromWarehouse", fields: [from_warehouse_id], references: [id], onUpdate: NoAction)
|
||||
departments_asset_transfers_to_department_idTodepartments departments? @relation("asset_transfers_to_department_idTodepartments", fields: [to_department_id], references: [id], onUpdate: NoAction)
|
||||
to_plant locations? @relation("TransferToPlant", fields: [to_plant_id], references: [id], onUpdate: NoAction)
|
||||
to_plant locations? @relation("TransferToPlant", fields: [to_plant_id], references: [id], onUpdate: NoAction)
|
||||
users_asset_transfers_to_user_idTousers users? @relation("asset_transfers_to_user_idTousers", fields: [to_user_id], references: [id], onUpdate: NoAction)
|
||||
to_warehouse locations? @relation("TransferToWarehouse", fields: [to_warehouse_id], references: [id], onUpdate: NoAction)
|
||||
to_warehouse locations? @relation("TransferToWarehouse", fields: [to_warehouse_id], references: [id], onUpdate: NoAction)
|
||||
users_asset_transfers_transferred_byTousers users? @relation("asset_transfers_transferred_byTousers", fields: [transferred_by], references: [id], onUpdate: NoAction)
|
||||
|
||||
@@index([asset_id], map: "idx_asset_transfers_asset_id")
|
||||
@ -167,61 +167,61 @@ model asset_transfers {
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
model assets {
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_code String @unique @db.VarChar(30)
|
||||
asset_name String @db.VarChar(200)
|
||||
id BigInt @id @default(autoincrement())
|
||||
asset_code String @unique @db.VarChar(30)
|
||||
asset_name String @db.VarChar(200)
|
||||
item_category_id BigInt
|
||||
item_subcategory_id BigInt?
|
||||
brand_model String? @db.VarChar(200)
|
||||
manufacturer String? @db.VarChar(200)
|
||||
serial_number String? @db.VarChar(100)
|
||||
part_number String? @db.VarChar(100)
|
||||
brand_model String? @db.VarChar(200)
|
||||
manufacturer String? @db.VarChar(200)
|
||||
serial_number String? @db.VarChar(100)
|
||||
part_number String? @db.VarChar(100)
|
||||
plant_id BigInt
|
||||
department_id BigInt?
|
||||
warehouse_id BigInt?
|
||||
location_detail String? @db.VarChar(200)
|
||||
location_detail String? @db.VarChar(200)
|
||||
assigned_to_user_id BigInt?
|
||||
vendor_id BigInt?
|
||||
po_id BigInt?
|
||||
grn_id BigInt?
|
||||
grn_item_id BigInt?
|
||||
purchase_date DateTime? @db.Date
|
||||
purchase_cost Decimal @default(0) @db.Decimal(15, 4)
|
||||
purchase_date DateTime? @db.Date
|
||||
purchase_cost Decimal @default(0) @db.Decimal(15, 4)
|
||||
useful_life_years Int?
|
||||
depreciation_method String? @db.VarChar(20)
|
||||
depreciation_rate Decimal? @db.Decimal(8, 4)
|
||||
salvage_value Decimal? @default(0) @db.Decimal(15, 4)
|
||||
warranty_expiry_date DateTime? @db.Date
|
||||
condition String @default("NEW") @db.VarChar(20)
|
||||
status String @default("IN_USE") @db.VarChar(30)
|
||||
qr_code_value String? @db.VarChar(100)
|
||||
disposal_date DateTime? @db.Date
|
||||
depreciation_method String? @db.VarChar(20)
|
||||
depreciation_rate Decimal? @db.Decimal(8, 4)
|
||||
salvage_value Decimal? @default(0) @db.Decimal(15, 4)
|
||||
warranty_expiry_date DateTime? @db.Date
|
||||
condition String @default("NEW") @db.VarChar(20)
|
||||
status String @default("IN_USE") @db.VarChar(30)
|
||||
qr_code_value String? @db.VarChar(100)
|
||||
disposal_date DateTime? @db.Date
|
||||
disposal_reason String?
|
||||
disposal_value Decimal? @db.Decimal(15, 4)
|
||||
disposal_value Decimal? @db.Decimal(15, 4)
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_amc_contracts asset_amc_contracts[]
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_amc_contracts asset_amc_contracts[]
|
||||
asset_attachments asset_attachments[]
|
||||
asset_insurance_policies asset_insurance_policies[]
|
||||
asset_service_visits asset_service_visits[]
|
||||
asset_transfers asset_transfers[]
|
||||
item_categories item_categories @relation(fields: [item_category_id], references: [id], onUpdate: NoAction)
|
||||
item_subcategories item_subcategories? @relation(fields: [item_subcategory_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_assigned_to_user_idTousers users? @relation("assets_assigned_to_user_idTousers", fields: [assigned_to_user_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_created_byTousers users? @relation("assets_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
departments departments? @relation(fields: [department_id], references: [id], onUpdate: NoAction)
|
||||
grn grn? @relation(fields: [grn_id], references: [id], onUpdate: NoAction)
|
||||
grn_items grn_items? @relation(fields: [grn_item_id], references: [id], onUpdate: NoAction)
|
||||
plant locations @relation("AssetPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
purchase_orders purchase_orders? @relation(fields: [po_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_updated_byTousers users? @relation("assets_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors_assets_vendor_idTovendors vendors? @relation("assets_vendor_idTovendors", fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
warehouse locations? @relation("AssetWarehouseLocation", fields: [warehouse_id], references: [id], onUpdate: NoAction)
|
||||
item_categories item_categories @relation(fields: [item_category_id], references: [id], onUpdate: NoAction)
|
||||
item_subcategories item_subcategories? @relation(fields: [item_subcategory_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_assigned_to_user_idTousers users? @relation("assets_assigned_to_user_idTousers", fields: [assigned_to_user_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_created_byTousers users? @relation("assets_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
departments departments? @relation(fields: [department_id], references: [id], onUpdate: NoAction)
|
||||
grn grn? @relation(fields: [grn_id], references: [id], onUpdate: NoAction)
|
||||
grn_items grn_items? @relation(fields: [grn_item_id], references: [id], onUpdate: NoAction)
|
||||
plant locations @relation("AssetPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
purchase_orders purchase_orders? @relation(fields: [po_id], references: [id], onUpdate: NoAction)
|
||||
users_assets_updated_byTousers users? @relation("assets_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors_assets_vendor_idTovendors vendors? @relation("assets_vendor_idTovendors", fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
warehouse locations? @relation("AssetWarehouseLocation", fields: [warehouse_id], references: [id], onUpdate: NoAction)
|
||||
|
||||
@@index([item_category_id], map: "idx_assets_item_category_id")
|
||||
@@index([item_subcategory_id], map: "idx_assets_item_subcategory_id")
|
||||
@ -247,26 +247,6 @@ model audit_logs {
|
||||
}
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
model brands {
|
||||
id BigInt @id @default(autoincrement())
|
||||
code String @unique @db.VarChar(30)
|
||||
name String @db.VarChar(150)
|
||||
brand_type String @default("OWN") @db.VarChar(20)
|
||||
contact_person String? @db.VarChar(150)
|
||||
phone String? @db.VarChar(15)
|
||||
email String? @db.VarChar(150)
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
users_brands_created_byTousers users? @relation("brands_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
users_brands_updated_byTousers users? @relation("brands_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
items items[]
|
||||
purchase_orders purchase_orders[]
|
||||
}
|
||||
|
||||
model delivery_terms {
|
||||
id BigInt @id @default(autoincrement())
|
||||
code String @unique @db.VarChar(30)
|
||||
@ -361,7 +341,7 @@ model grn {
|
||||
users_grn_received_byTousers users? @relation("grn_received_byTousers", fields: [received_by], references: [id], onUpdate: NoAction)
|
||||
users_grn_updated_byTousers users? @relation("grn_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
warehouse locations @relation("GRNWarehouseLocation", fields: [warehouse_id], references: [id], onUpdate: NoAction)
|
||||
warehouse locations @relation("GRNWarehouseLocation", fields: [warehouse_id], references: [id], onUpdate: NoAction)
|
||||
grn_attachments grn_attachments[]
|
||||
grn_items grn_items[]
|
||||
|
||||
@ -423,6 +403,7 @@ model gst_rates {
|
||||
is_active Boolean @default(true)
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
hsn_codes hsn_codes[]
|
||||
items items[]
|
||||
purchase_order_items purchase_order_items[]
|
||||
}
|
||||
@ -431,9 +412,11 @@ model hsn_codes {
|
||||
id BigInt @id @default(autoincrement())
|
||||
code String @unique @db.VarChar(20)
|
||||
description String?
|
||||
gst_rate_id BigInt?
|
||||
is_active Boolean @default(true)
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
gst_rates gst_rates? @relation(fields: [gst_rate_id], references: [id], onUpdate: NoAction)
|
||||
items items[]
|
||||
purchase_order_items purchase_order_items[]
|
||||
}
|
||||
@ -442,6 +425,7 @@ model item_categories {
|
||||
id BigInt @id @default(autoincrement())
|
||||
code String @unique @db.VarChar(30)
|
||||
name String @db.VarChar(100)
|
||||
category_type String @default("STOCK") @db.VarChar(10)
|
||||
code_prefix String? @unique @db.VarChar(10)
|
||||
default_useful_life_years Int?
|
||||
default_depreciation_method String? @db.VarChar(20)
|
||||
@ -485,7 +469,6 @@ model items {
|
||||
uom_id BigInt
|
||||
hsn_code_id BigInt?
|
||||
gst_rate_id BigInt?
|
||||
brand_id BigInt?
|
||||
is_asset_item Boolean @default(false)
|
||||
description String?
|
||||
specification String?
|
||||
@ -498,7 +481,6 @@ model items {
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
grn_items grn_items[]
|
||||
brands brands? @relation(fields: [brand_id], references: [id], onUpdate: NoAction)
|
||||
users_items_created_byTousers users? @relation("items_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
gst_rates gst_rates? @relation(fields: [gst_rate_id], references: [id], onUpdate: NoAction)
|
||||
hsn_codes hsn_codes? @relation(fields: [hsn_code_id], references: [id], onUpdate: NoAction)
|
||||
@ -568,38 +550,38 @@ model permissions {
|
||||
}
|
||||
|
||||
model locations {
|
||||
id BigInt @id @default(autoincrement())
|
||||
type String @db.VarChar(20)
|
||||
code String @db.VarChar(30)
|
||||
name String @db.VarChar(150)
|
||||
parent_id BigInt?
|
||||
gstin String? @db.VarChar(15)
|
||||
address String?
|
||||
city String? @db.VarChar(100)
|
||||
state String? @db.VarChar(100)
|
||||
pincode String? @db.VarChar(10)
|
||||
phone String? @db.VarChar(15)
|
||||
location String? @db.VarChar(200)
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
transfers_from_plant asset_transfers[] @relation("TransferFromPlant")
|
||||
transfers_to_plant asset_transfers[] @relation("TransferToPlant")
|
||||
transfers_from_wh asset_transfers[] @relation("TransferFromWarehouse")
|
||||
transfers_to_wh asset_transfers[] @relation("TransferToWarehouse")
|
||||
assets_plant assets[] @relation("AssetPlantLocation")
|
||||
assets_warehouse assets[] @relation("AssetWarehouseLocation")
|
||||
grn_warehouse grn[] @relation("GRNWarehouseLocation")
|
||||
parent locations? @relation("LocationHierarchy", fields: [parent_id], references: [id], onUpdate: NoAction)
|
||||
children locations[] @relation("LocationHierarchy")
|
||||
po_plant purchase_orders[] @relation("POPlantLocation")
|
||||
po_warehouse purchase_orders[] @relation("POWarehouseLocation")
|
||||
users_plant users[] @relation("UserPlantLocation")
|
||||
users_created users? @relation("locations_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction, map: "fk_locations_created_by")
|
||||
users_updated users? @relation("locations_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction, map: "fk_locations_updated_by")
|
||||
id BigInt @id @default(autoincrement())
|
||||
type String @db.VarChar(20)
|
||||
code String @db.VarChar(30)
|
||||
name String @db.VarChar(150)
|
||||
parent_id BigInt?
|
||||
gstin String? @db.VarChar(15)
|
||||
address String?
|
||||
city String? @db.VarChar(100)
|
||||
state String? @db.VarChar(100)
|
||||
pincode String? @db.VarChar(10)
|
||||
phone String? @db.VarChar(15)
|
||||
location String? @db.VarChar(200)
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
transfers_from_plant asset_transfers[] @relation("TransferFromPlant")
|
||||
transfers_to_plant asset_transfers[] @relation("TransferToPlant")
|
||||
transfers_from_wh asset_transfers[] @relation("TransferFromWarehouse")
|
||||
transfers_to_wh asset_transfers[] @relation("TransferToWarehouse")
|
||||
assets_plant assets[] @relation("AssetPlantLocation")
|
||||
assets_warehouse assets[] @relation("AssetWarehouseLocation")
|
||||
grn_warehouse grn[] @relation("GRNWarehouseLocation")
|
||||
parent locations? @relation("LocationHierarchy", fields: [parent_id], references: [id], onUpdate: NoAction)
|
||||
children locations[] @relation("LocationHierarchy")
|
||||
po_plant purchase_orders[] @relation("POPlantLocation")
|
||||
po_warehouse purchase_orders[] @relation("POWarehouseLocation")
|
||||
users_plant users[] @relation("UserPlantLocation")
|
||||
users_created users? @relation("locations_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction, map: "fk_locations_created_by")
|
||||
users_updated users? @relation("locations_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction, map: "fk_locations_updated_by")
|
||||
|
||||
@@index([type], map: "idx_locations_type")
|
||||
@@index([parent_id], map: "idx_locations_parent_id")
|
||||
@ -673,11 +655,9 @@ model purchase_orders {
|
||||
id BigInt @id @default(autoincrement())
|
||||
po_number String @unique @db.VarChar(30)
|
||||
po_date DateTime @db.Date
|
||||
po_type String @db.VarChar(30)
|
||||
vendor_id BigInt
|
||||
plant_id BigInt
|
||||
warehouse_id BigInt?
|
||||
brand_id BigInt?
|
||||
payment_term_id BigInt?
|
||||
delivery_term_id BigInt?
|
||||
expected_delivery_date DateTime? @db.Date
|
||||
@ -707,16 +687,15 @@ model purchase_orders {
|
||||
po_approvals po_approvals[]
|
||||
po_attachments po_attachments[]
|
||||
purchase_order_items purchase_order_items[]
|
||||
brands brands? @relation(fields: [brand_id], references: [id], onUpdate: NoAction)
|
||||
users_purchase_orders_created_byTousers users? @relation("purchase_orders_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
delivery_terms delivery_terms? @relation(fields: [delivery_term_id], references: [id], onUpdate: NoAction)
|
||||
purchase_orders purchase_orders? @relation("purchase_ordersTopurchase_orders", fields: [parent_po_id], references: [id], onUpdate: NoAction)
|
||||
other_purchase_orders purchase_orders[] @relation("purchase_ordersTopurchase_orders")
|
||||
payment_terms payment_terms? @relation(fields: [payment_term_id], references: [id], onUpdate: NoAction)
|
||||
plant locations @relation("POPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
plant locations @relation("POPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
users_purchase_orders_updated_byTousers users? @relation("purchase_orders_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
vendors vendors @relation(fields: [vendor_id], references: [id], onUpdate: NoAction)
|
||||
warehouse locations? @relation("POWarehouseLocation", fields: [warehouse_id], references: [id], onDelete: Restrict, onUpdate: NoAction)
|
||||
warehouse locations? @relation("POWarehouseLocation", fields: [warehouse_id], references: [id], onDelete: Restrict, onUpdate: NoAction)
|
||||
|
||||
@@index([created_at], map: "idx_po_created_at")
|
||||
@@index([po_date], map: "idx_po_po_date")
|
||||
@ -795,94 +774,92 @@ model uom {
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
model users {
|
||||
id BigInt @id @default(autoincrement())
|
||||
employee_code String @unique @db.VarChar(30)
|
||||
full_name String @db.VarChar(200)
|
||||
email String @unique @db.VarChar(200)
|
||||
mobile String? @db.VarChar(255)
|
||||
mobile_index String? @db.VarChar(64)
|
||||
password_hash String @db.VarChar(255)
|
||||
avatar_path String? @db.VarChar(500)
|
||||
department_id BigInt?
|
||||
designation_id BigInt?
|
||||
plant_id BigInt?
|
||||
reporting_to BigInt?
|
||||
status String @default("active") @db.VarChar(20)
|
||||
is_active Boolean @default(true)
|
||||
failed_login_attempts Int @default(0)
|
||||
locked_until DateTime? @db.Timestamptz(6)
|
||||
last_login_at DateTime? @db.Timestamptz(6)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
asset_amc_contracts_asset_amc_contracts_created_byTousers asset_amc_contracts[] @relation("asset_amc_contracts_created_byTousers")
|
||||
asset_amc_contracts_asset_amc_contracts_updated_byTousers asset_amc_contracts[] @relation("asset_amc_contracts_updated_byTousers")
|
||||
id BigInt @id @default(autoincrement())
|
||||
employee_code String @unique @db.VarChar(30)
|
||||
full_name String @db.VarChar(200)
|
||||
email String @unique @db.VarChar(200)
|
||||
mobile String? @db.VarChar(255)
|
||||
mobile_index String? @db.VarChar(64)
|
||||
password_hash String @db.VarChar(255)
|
||||
avatar_path String? @db.VarChar(500)
|
||||
department_id BigInt?
|
||||
designation_id BigInt?
|
||||
plant_id BigInt?
|
||||
reporting_to BigInt?
|
||||
status String @default("active") @db.VarChar(20)
|
||||
is_active Boolean @default(true)
|
||||
failed_login_attempts Int @default(0)
|
||||
locked_until DateTime? @db.Timestamptz(6)
|
||||
last_login_at DateTime? @db.Timestamptz(6)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
asset_attachments asset_attachments[]
|
||||
asset_amc_contracts_asset_amc_contracts_created_byTousers asset_amc_contracts[] @relation("asset_amc_contracts_created_byTousers")
|
||||
asset_amc_contracts_asset_amc_contracts_updated_byTousers asset_amc_contracts[] @relation("asset_amc_contracts_updated_byTousers")
|
||||
asset_insurance_policies_asset_insurance_policies_created_byTousers asset_insurance_policies[] @relation("asset_insurance_policies_created_byTousers")
|
||||
asset_insurance_policies_asset_insurance_policies_updated_byTousers asset_insurance_policies[] @relation("asset_insurance_policies_updated_byTousers")
|
||||
asset_service_visits_asset_service_visits_created_byTousers asset_service_visits[] @relation("asset_service_visits_created_byTousers")
|
||||
asset_service_visits_asset_service_visits_updated_byTousers asset_service_visits[] @relation("asset_service_visits_updated_byTousers")
|
||||
asset_transfers_asset_transfers_from_user_idTousers asset_transfers[] @relation("asset_transfers_from_user_idTousers")
|
||||
asset_transfers_asset_transfers_to_user_idTousers asset_transfers[] @relation("asset_transfers_to_user_idTousers")
|
||||
asset_transfers_asset_transfers_transferred_byTousers asset_transfers[] @relation("asset_transfers_transferred_byTousers")
|
||||
assets_assets_assigned_to_user_idTousers assets[] @relation("assets_assigned_to_user_idTousers")
|
||||
assets_assets_created_byTousers assets[] @relation("assets_created_byTousers")
|
||||
assets_assets_updated_byTousers assets[] @relation("assets_updated_byTousers")
|
||||
audit_logs audit_logs[]
|
||||
brands_brands_created_byTousers brands[] @relation("brands_created_byTousers")
|
||||
brands_brands_updated_byTousers brands[] @relation("brands_updated_byTousers")
|
||||
delivery_terms_delivery_terms_created_byTousers delivery_terms[] @relation("delivery_terms_created_byTousers")
|
||||
delivery_terms_delivery_terms_updated_byTousers delivery_terms[] @relation("delivery_terms_updated_byTousers")
|
||||
document_series_document_series_created_byTousers document_series[] @relation("document_series_created_byTousers")
|
||||
document_series_document_series_updated_byTousers document_series[] @relation("document_series_updated_byTousers")
|
||||
grn_grn_cancelled_byTousers grn[] @relation("grn_cancelled_byTousers")
|
||||
grn_grn_created_byTousers grn[] @relation("grn_created_byTousers")
|
||||
grn_grn_quality_checked_byTousers grn[] @relation("grn_quality_checked_byTousers")
|
||||
grn_grn_received_byTousers grn[] @relation("grn_received_byTousers")
|
||||
grn_grn_updated_byTousers grn[] @relation("grn_updated_byTousers")
|
||||
grn_attachments grn_attachments[]
|
||||
item_categories_item_categories_created_byTousers item_categories[] @relation("item_categories_created_byTousers")
|
||||
item_categories_item_categories_updated_byTousers item_categories[] @relation("item_categories_updated_byTousers")
|
||||
item_subcategories_item_subcategories_created_byTousers item_subcategories[] @relation("item_subcategories_created_byTousers")
|
||||
item_subcategories_item_subcategories_updated_byTousers item_subcategories[] @relation("item_subcategories_updated_byTousers")
|
||||
items_items_created_byTousers items[] @relation("items_created_byTousers")
|
||||
items_items_updated_byTousers items[] @relation("items_updated_byTousers")
|
||||
password_reset_tokens password_reset_tokens[]
|
||||
payment_terms_payment_terms_created_byTousers payment_terms[] @relation("payment_terms_created_byTousers")
|
||||
payment_terms_payment_terms_updated_byTousers payment_terms[] @relation("payment_terms_updated_byTousers")
|
||||
locations_locations_created_byTousers locations[] @relation("locations_created_byTousers")
|
||||
locations_locations_updated_byTousers locations[] @relation("locations_updated_byTousers")
|
||||
po_approvals po_approvals[]
|
||||
po_attachments po_attachments[]
|
||||
purchase_orders_purchase_orders_created_byTousers purchase_orders[] @relation("purchase_orders_created_byTousers")
|
||||
purchase_orders_purchase_orders_updated_byTousers purchase_orders[] @relation("purchase_orders_updated_byTousers")
|
||||
refresh_tokens refresh_tokens[]
|
||||
user_roles user_roles[]
|
||||
roles_roles_created_byTousers roles[] @relation("roles_created_byTousers")
|
||||
roles_roles_updated_byTousers roles[] @relation("roles_updated_byTousers")
|
||||
uom_uom_created_byTousers uom[] @relation("uom_created_byTousers")
|
||||
uom_uom_updated_byTousers uom[] @relation("uom_updated_byTousers")
|
||||
users_users_created_byTousers users? @relation("users_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
other_users_users_created_byTousers users[] @relation("users_created_byTousers")
|
||||
departments departments? @relation(fields: [department_id], references: [id], onUpdate: NoAction)
|
||||
designations designations? @relation(fields: [designation_id], references: [id], onUpdate: NoAction)
|
||||
plant_location locations? @relation("UserPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
users_users_reporting_toTousers users? @relation("users_reporting_toTousers", fields: [reporting_to], references: [id], onUpdate: NoAction)
|
||||
other_users_users_reporting_toTousers users[] @relation("users_reporting_toTousers")
|
||||
users_users_updated_byTousers users? @relation("users_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
other_users_users_updated_byTousers users[] @relation("users_updated_byTousers")
|
||||
vendor_addresses_vendor_addresses_created_byTousers vendor_addresses[] @relation("vendor_addresses_created_byTousers")
|
||||
vendor_addresses_vendor_addresses_updated_byTousers vendor_addresses[] @relation("vendor_addresses_updated_byTousers")
|
||||
vendor_bank_details_vendor_bank_details_created_byTousers vendor_bank_details[] @relation("vendor_bank_details_created_byTousers")
|
||||
vendor_bank_details_vendor_bank_details_updated_byTousers vendor_bank_details[] @relation("vendor_bank_details_updated_byTousers")
|
||||
vendor_contacts_vendor_contacts_created_byTousers vendor_contacts[] @relation("vendor_contacts_created_byTousers")
|
||||
vendor_contacts_vendor_contacts_updated_byTousers vendor_contacts[] @relation("vendor_contacts_updated_byTousers")
|
||||
vendor_item_mapping_vendor_item_mapping_created_byTousers vendor_item_mapping[] @relation("vendor_item_mapping_created_byTousers")
|
||||
vendor_item_mapping_vendor_item_mapping_updated_byTousers vendor_item_mapping[] @relation("vendor_item_mapping_updated_byTousers")
|
||||
vendors_vendors_created_byTousers vendors[] @relation("vendors_created_byTousers")
|
||||
vendors_vendors_updated_byTousers vendors[] @relation("vendors_updated_byTousers")
|
||||
asset_service_visits_asset_service_visits_created_byTousers asset_service_visits[] @relation("asset_service_visits_created_byTousers")
|
||||
asset_service_visits_asset_service_visits_updated_byTousers asset_service_visits[] @relation("asset_service_visits_updated_byTousers")
|
||||
asset_transfers_asset_transfers_from_user_idTousers asset_transfers[] @relation("asset_transfers_from_user_idTousers")
|
||||
asset_transfers_asset_transfers_to_user_idTousers asset_transfers[] @relation("asset_transfers_to_user_idTousers")
|
||||
asset_transfers_asset_transfers_transferred_byTousers asset_transfers[] @relation("asset_transfers_transferred_byTousers")
|
||||
assets_assets_assigned_to_user_idTousers assets[] @relation("assets_assigned_to_user_idTousers")
|
||||
assets_assets_created_byTousers assets[] @relation("assets_created_byTousers")
|
||||
assets_assets_updated_byTousers assets[] @relation("assets_updated_byTousers")
|
||||
audit_logs audit_logs[]
|
||||
delivery_terms_delivery_terms_created_byTousers delivery_terms[] @relation("delivery_terms_created_byTousers")
|
||||
delivery_terms_delivery_terms_updated_byTousers delivery_terms[] @relation("delivery_terms_updated_byTousers")
|
||||
document_series_document_series_created_byTousers document_series[] @relation("document_series_created_byTousers")
|
||||
document_series_document_series_updated_byTousers document_series[] @relation("document_series_updated_byTousers")
|
||||
grn_grn_cancelled_byTousers grn[] @relation("grn_cancelled_byTousers")
|
||||
grn_grn_created_byTousers grn[] @relation("grn_created_byTousers")
|
||||
grn_grn_quality_checked_byTousers grn[] @relation("grn_quality_checked_byTousers")
|
||||
grn_grn_received_byTousers grn[] @relation("grn_received_byTousers")
|
||||
grn_grn_updated_byTousers grn[] @relation("grn_updated_byTousers")
|
||||
grn_attachments grn_attachments[]
|
||||
item_categories_item_categories_created_byTousers item_categories[] @relation("item_categories_created_byTousers")
|
||||
item_categories_item_categories_updated_byTousers item_categories[] @relation("item_categories_updated_byTousers")
|
||||
item_subcategories_item_subcategories_created_byTousers item_subcategories[] @relation("item_subcategories_created_byTousers")
|
||||
item_subcategories_item_subcategories_updated_byTousers item_subcategories[] @relation("item_subcategories_updated_byTousers")
|
||||
items_items_created_byTousers items[] @relation("items_created_byTousers")
|
||||
items_items_updated_byTousers items[] @relation("items_updated_byTousers")
|
||||
password_reset_tokens password_reset_tokens[]
|
||||
payment_terms_payment_terms_created_byTousers payment_terms[] @relation("payment_terms_created_byTousers")
|
||||
payment_terms_payment_terms_updated_byTousers payment_terms[] @relation("payment_terms_updated_byTousers")
|
||||
locations_locations_created_byTousers locations[] @relation("locations_created_byTousers")
|
||||
locations_locations_updated_byTousers locations[] @relation("locations_updated_byTousers")
|
||||
po_approvals po_approvals[]
|
||||
po_attachments po_attachments[]
|
||||
purchase_orders_purchase_orders_created_byTousers purchase_orders[] @relation("purchase_orders_created_byTousers")
|
||||
purchase_orders_purchase_orders_updated_byTousers purchase_orders[] @relation("purchase_orders_updated_byTousers")
|
||||
refresh_tokens refresh_tokens[]
|
||||
user_roles user_roles[]
|
||||
roles_roles_created_byTousers roles[] @relation("roles_created_byTousers")
|
||||
roles_roles_updated_byTousers roles[] @relation("roles_updated_byTousers")
|
||||
uom_uom_created_byTousers uom[] @relation("uom_created_byTousers")
|
||||
uom_uom_updated_byTousers uom[] @relation("uom_updated_byTousers")
|
||||
users_users_created_byTousers users? @relation("users_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
other_users_users_created_byTousers users[] @relation("users_created_byTousers")
|
||||
departments departments? @relation(fields: [department_id], references: [id], onUpdate: NoAction)
|
||||
designations designations? @relation(fields: [designation_id], references: [id], onUpdate: NoAction)
|
||||
plant_location locations? @relation("UserPlantLocation", fields: [plant_id], references: [id], onUpdate: NoAction)
|
||||
users_users_reporting_toTousers users? @relation("users_reporting_toTousers", fields: [reporting_to], references: [id], onUpdate: NoAction)
|
||||
other_users_users_reporting_toTousers users[] @relation("users_reporting_toTousers")
|
||||
users_users_updated_byTousers users? @relation("users_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
other_users_users_updated_byTousers users[] @relation("users_updated_byTousers")
|
||||
vendor_addresses_vendor_addresses_created_byTousers vendor_addresses[] @relation("vendor_addresses_created_byTousers")
|
||||
vendor_addresses_vendor_addresses_updated_byTousers vendor_addresses[] @relation("vendor_addresses_updated_byTousers")
|
||||
vendor_bank_details_vendor_bank_details_created_byTousers vendor_bank_details[] @relation("vendor_bank_details_created_byTousers")
|
||||
vendor_bank_details_vendor_bank_details_updated_byTousers vendor_bank_details[] @relation("vendor_bank_details_updated_byTousers")
|
||||
vendor_contacts_vendor_contacts_created_byTousers vendor_contacts[] @relation("vendor_contacts_created_byTousers")
|
||||
vendor_contacts_vendor_contacts_updated_byTousers vendor_contacts[] @relation("vendor_contacts_updated_byTousers")
|
||||
vendor_item_mapping_vendor_item_mapping_created_byTousers vendor_item_mapping[] @relation("vendor_item_mapping_created_byTousers")
|
||||
vendor_item_mapping_vendor_item_mapping_updated_byTousers vendor_item_mapping[] @relation("vendor_item_mapping_updated_byTousers")
|
||||
vendors_vendors_created_byTousers vendors[] @relation("vendors_created_byTousers")
|
||||
vendors_vendors_updated_byTousers vendors[] @relation("vendors_updated_byTousers")
|
||||
}
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
@ -968,36 +945,36 @@ model vendor_item_mapping {
|
||||
|
||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||
model vendors {
|
||||
id BigInt @id @default(autoincrement())
|
||||
vendor_code String @unique @db.VarChar(30)
|
||||
vendor_name String @db.VarChar(200)
|
||||
vendor_type String @db.VarChar(30)
|
||||
gst_treatment String? @db.VarChar(30)
|
||||
source_of_supply String? @db.VarChar(100)
|
||||
gstin String? @db.VarChar(15)
|
||||
pan String? @db.VarChar(10)
|
||||
payment_term_id BigInt?
|
||||
credit_period_days Int @default(0)
|
||||
status String @default("active") @db.VarChar(20)
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
assets_assets_vendor_idTovendors assets[] @relation("assets_vendor_idTovendors")
|
||||
asset_amc_contracts asset_amc_contracts[]
|
||||
asset_service_visits asset_service_visits[]
|
||||
grn grn[]
|
||||
purchase_orders purchase_orders[]
|
||||
vendor_addresses vendor_addresses[]
|
||||
vendor_bank_details vendor_bank_details[]
|
||||
vendor_contacts vendor_contacts[]
|
||||
vendor_item_mapping vendor_item_mapping[]
|
||||
users_vendors_created_byTousers users? @relation("vendors_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
payment_terms payment_terms? @relation(fields: [payment_term_id], references: [id], onUpdate: NoAction)
|
||||
users_vendors_updated_byTousers users? @relation("vendors_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
id BigInt @id @default(autoincrement())
|
||||
vendor_code String @unique @db.VarChar(30)
|
||||
vendor_name String @db.VarChar(200)
|
||||
vendor_type String @db.VarChar(30)
|
||||
gst_treatment String? @db.VarChar(30)
|
||||
source_of_supply String? @db.VarChar(100)
|
||||
gstin String? @db.VarChar(15)
|
||||
pan String? @db.VarChar(10)
|
||||
payment_term_id BigInt?
|
||||
credit_period_days Int @default(0)
|
||||
status String @default("active") @db.VarChar(20)
|
||||
remarks String?
|
||||
is_active Boolean @default(true)
|
||||
created_by BigInt?
|
||||
updated_by BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
deleted_at DateTime? @db.Timestamptz(6)
|
||||
assets_assets_vendor_idTovendors assets[] @relation("assets_vendor_idTovendors")
|
||||
asset_amc_contracts asset_amc_contracts[]
|
||||
asset_service_visits asset_service_visits[]
|
||||
grn grn[]
|
||||
purchase_orders purchase_orders[]
|
||||
vendor_addresses vendor_addresses[]
|
||||
vendor_bank_details vendor_bank_details[]
|
||||
vendor_contacts vendor_contacts[]
|
||||
vendor_item_mapping vendor_item_mapping[]
|
||||
users_vendors_created_byTousers users? @relation("vendors_created_byTousers", fields: [created_by], references: [id], onUpdate: NoAction)
|
||||
payment_terms payment_terms? @relation(fields: [payment_term_id], references: [id], onUpdate: NoAction)
|
||||
users_vendors_updated_byTousers users? @relation("vendors_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction)
|
||||
|
||||
@@index([vendor_name(ops: raw("gin_trgm_ops"))], map: "idx_vendors_name_trgm", type: Gin)
|
||||
}
|
||||
|
||||
25
scripts/patch-drop-brands.sql
Normal file
25
scripts/patch-drop-brands.sql
Normal file
@ -0,0 +1,25 @@
|
||||
-- Remove brand_id from items & purchase_orders and drop the brands master table.
|
||||
-- WARNING: destructive. Export brand data first if it must be retained.
|
||||
-- Idempotent: safe to re-run.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 0) Drop dependent view (selects purchase_orders.*); recreated by patch-purchase-orders-drop-po-type.sql
|
||||
DROP VIEW IF EXISTS v_purchase_orders CASCADE;
|
||||
|
||||
-- 1) Drop FK constraints (name may vary by DB; drop defensively)
|
||||
ALTER TABLE items DROP CONSTRAINT IF EXISTS items_brand_id_fkey;
|
||||
ALTER TABLE purchase_orders DROP CONSTRAINT IF EXISTS purchase_orders_brand_id_fkey;
|
||||
|
||||
-- 2) Drop columns
|
||||
ALTER TABLE items DROP COLUMN IF EXISTS brand_id;
|
||||
ALTER TABLE purchase_orders DROP COLUMN IF EXISTS brand_id;
|
||||
|
||||
-- 3) Drop the brands master (CASCADE removes its check/unique constraints and user FKs)
|
||||
DROP TABLE IF EXISTS brands CASCADE;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Verify:
|
||||
-- SELECT column_name FROM information_schema.columns WHERE table_name = 'items' AND column_name = 'brand_id';
|
||||
-- SELECT to_regclass('public.brands'); -- expect NULL
|
||||
32
scripts/patch-hsn-codes-gst-rate.sql
Normal file
32
scripts/patch-hsn-codes-gst-rate.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- Link HSN codes to a default GST rate
|
||||
-- Adds hsn_codes.gst_rate_id (nullable) FK -> gst_rates(id)
|
||||
-- Idempotent: safe to re-run.
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE hsn_codes
|
||||
ADD COLUMN IF NOT EXISTS gst_rate_id BIGINT;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'hsn_codes_gst_rate_id_fkey'
|
||||
) THEN
|
||||
ALTER TABLE hsn_codes
|
||||
ADD CONSTRAINT hsn_codes_gst_rate_id_fkey
|
||||
FOREIGN KEY (gst_rate_id) REFERENCES gst_rates(id);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_hsn_codes_gst_rate_id ON hsn_codes (gst_rate_id);
|
||||
|
||||
-- Optional backfill: default existing HSN codes to the 18% slab (adjust per business rules)
|
||||
-- UPDATE hsn_codes h
|
||||
-- SET gst_rate_id = g.id
|
||||
-- FROM gst_rates g
|
||||
-- WHERE g.rate_pct = 18 AND g.is_active = TRUE AND h.gst_rate_id IS NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Verify:
|
||||
-- SELECT h.code, g.rate_pct FROM hsn_codes h LEFT JOIN gst_rates g ON g.id = h.gst_rate_id ORDER BY h.code;
|
||||
41
scripts/patch-item-categories-type.sql
Normal file
41
scripts/patch-item-categories-type.sql
Normal file
@ -0,0 +1,41 @@
|
||||
-- Add category_type to item_categories: STOCK | ASSET
|
||||
-- STOCK categories are shown in the Items module; ASSET categories in the Assets module.
|
||||
-- Idempotent: safe to re-run.
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE item_categories
|
||||
ADD COLUMN IF NOT EXISTS category_type VARCHAR(10);
|
||||
|
||||
-- Backfill existing rows: treat categories carrying asset defaults as ASSET, else STOCK
|
||||
UPDATE item_categories
|
||||
SET category_type = CASE
|
||||
WHEN code_prefix IS NOT NULL
|
||||
OR default_useful_life_years IS NOT NULL
|
||||
OR default_depreciation_method IS NOT NULL
|
||||
THEN 'ASSET'
|
||||
ELSE 'STOCK'
|
||||
END
|
||||
WHERE category_type IS NULL;
|
||||
|
||||
ALTER TABLE item_categories
|
||||
ALTER COLUMN category_type SET DEFAULT 'STOCK';
|
||||
|
||||
ALTER TABLE item_categories
|
||||
ALTER COLUMN category_type SET NOT NULL;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'item_categories_category_type_check'
|
||||
) THEN
|
||||
ALTER TABLE item_categories
|
||||
ADD CONSTRAINT item_categories_category_type_check
|
||||
CHECK (category_type IN ('STOCK', 'ASSET'));
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Verify:
|
||||
-- SELECT category_type, COUNT(*) FROM item_categories WHERE deleted_at IS NULL GROUP BY 1;
|
||||
32
scripts/patch-purchase-orders-drop-po-type.sql
Normal file
32
scripts/patch-purchase-orders-drop-po-type.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- Remove po_type from purchase_orders.
|
||||
-- PO classification is now derived from the linked vendor (vendors.vendor_type).
|
||||
-- Recreates v_purchase_orders (which selects po.*) so it no longer exposes po_type.
|
||||
-- Idempotent: safe to re-run.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- The view selects po.* so it must be dropped before the column can be removed
|
||||
DROP VIEW IF EXISTS v_purchase_orders CASCADE;
|
||||
|
||||
ALTER TABLE purchase_orders DROP COLUMN IF EXISTS po_type;
|
||||
|
||||
CREATE VIEW v_purchase_orders AS
|
||||
SELECT
|
||||
po.*,
|
||||
pl.code AS plant_code,
|
||||
pl.name AS plant_name,
|
||||
wh.code AS warehouse_code,
|
||||
wh.name AS warehouse_name,
|
||||
v.vendor_code,
|
||||
v.vendor_name,
|
||||
v.vendor_type
|
||||
FROM purchase_orders po
|
||||
JOIN locations pl ON pl.id = po.plant_id AND pl.type = 'plant'
|
||||
LEFT JOIN locations wh ON wh.id = po.warehouse_id AND wh.type = 'warehouse'
|
||||
JOIN vendors v ON v.id = po.vendor_id
|
||||
WHERE po.deleted_at IS NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Verify:
|
||||
-- SELECT column_name FROM information_schema.columns WHERE table_name = 'purchase_orders' AND column_name = 'po_type';
|
||||
@ -4,7 +4,6 @@ tags:
|
||||
- name: Item Categories
|
||||
- name: Item Subcategories
|
||||
- name: Items
|
||||
- name: Brands
|
||||
- name: GST Rates
|
||||
- name: HSN Codes
|
||||
- name: Payment Terms
|
||||
@ -109,10 +108,11 @@ components:
|
||||
is_active: { type: boolean, example: true }
|
||||
ItemCategoriesCreateBody:
|
||||
type: object
|
||||
required: [code, name]
|
||||
required: [code, name, category_type]
|
||||
properties:
|
||||
code: { type: string, example: 'RAW' }
|
||||
name: { type: string, example: 'Raw Material' }
|
||||
category_type: { type: string, enum: [STOCK, ASSET], example: STOCK, description: 'STOCK categories are shown in the Items module; ASSET categories in the Assets module' }
|
||||
code_prefix: { type: string, nullable: true, example: 'MCH', description: Optional; used for asset code series when category is used for assets }
|
||||
default_useful_life_years: { type: integer, nullable: true, example: 15 }
|
||||
default_depreciation_method: { type: string, nullable: true, enum: [SLM, WDV, OTHER], example: SLM }
|
||||
@ -123,6 +123,7 @@ components:
|
||||
properties:
|
||||
code: { type: string, example: 'RAW' }
|
||||
name: { type: string, example: 'Raw Material' }
|
||||
category_type: { type: string, enum: [STOCK, ASSET], example: STOCK }
|
||||
code_prefix: { type: string, nullable: true, example: 'MCH' }
|
||||
default_useful_life_years: { type: integer, nullable: true, example: 15 }
|
||||
default_depreciation_method: { type: string, nullable: true, enum: [SLM, WDV, OTHER], example: SLM }
|
||||
@ -168,7 +169,6 @@ components:
|
||||
uom_id: { type: integer, example: 1 }
|
||||
hsn_code_id: { type: integer, nullable: true, example: 1 }
|
||||
gst_rate_id: { type: integer, nullable: true, example: 4 }
|
||||
brand_id: { type: integer, nullable: true, example: 1 }
|
||||
is_asset_item: { type: boolean, example: false }
|
||||
description: { type: string, example: 'Raw material' }
|
||||
specification: { type: string, example: '96% purity' }
|
||||
@ -185,7 +185,6 @@ components:
|
||||
uom_id: { type: integer, example: 1 }
|
||||
hsn_code_id: { type: integer, nullable: true, example: 1 }
|
||||
gst_rate_id: { type: integer, nullable: true, example: 4 }
|
||||
brand_id: { type: integer, nullable: true, example: 1 }
|
||||
is_asset_item: { type: boolean, example: false }
|
||||
description: { type: string, example: 'Raw material' }
|
||||
specification: { type: string, example: '96% purity' }
|
||||
@ -237,35 +236,6 @@ components:
|
||||
id: { type: string }
|
||||
rate_pct: { type: number }
|
||||
description: { type: string, nullable: true }
|
||||
brand:
|
||||
type: object
|
||||
nullable: true
|
||||
properties:
|
||||
id: { type: string }
|
||||
code: { type: string }
|
||||
name: { type: string }
|
||||
BrandsCreateBody:
|
||||
type: object
|
||||
required: [code, name, brand_type]
|
||||
properties:
|
||||
code: { type: string, example: 'OWN01' }
|
||||
name: { type: string, example: 'Bharat Clean' }
|
||||
brand_type: { type: string, enum: [OWN, OEM, THIRD_PARTY], example: OWN }
|
||||
contact_person: { type: string, example: 'Ravi' }
|
||||
phone: { type: string, example: '9876543210' }
|
||||
email: { type: string, example: 'ops@bharaterp.com' }
|
||||
is_active: { type: boolean, example: true }
|
||||
BrandsUpdateBody:
|
||||
type: object
|
||||
minProperties: 1
|
||||
properties:
|
||||
code: { type: string, example: 'OWN01' }
|
||||
name: { type: string, example: 'Bharat Clean' }
|
||||
brand_type: { type: string, enum: [OWN, OEM, THIRD_PARTY], example: OWN }
|
||||
contact_person: { type: string, example: 'Ravi' }
|
||||
phone: { type: string, example: '9876543210' }
|
||||
email: { type: string, example: 'ops@bharaterp.com' }
|
||||
is_active: { type: boolean, example: true }
|
||||
GstRatesCreateBody:
|
||||
type: object
|
||||
required: [rate_pct]
|
||||
@ -286,6 +256,7 @@ components:
|
||||
properties:
|
||||
code: { type: string, example: '34029099', description: '4–8 digit HSN/SAC code' }
|
||||
description: { type: string, example: 'Organic surface-active agents' }
|
||||
gst_rate_id: { type: integer, nullable: true, example: 4, description: 'Default GST rate for this HSN' }
|
||||
is_active: { type: boolean, example: true }
|
||||
HsnCodesUpdateBody:
|
||||
type: object
|
||||
@ -293,6 +264,7 @@ components:
|
||||
properties:
|
||||
code: { type: string, example: '34029099' }
|
||||
description: { type: string, example: 'Organic surface-active agents' }
|
||||
gst_rate_id: { type: integer, nullable: true, example: 4 }
|
||||
is_active: { type: boolean, example: true }
|
||||
PaymentTermsCreateBody:
|
||||
type: object
|
||||
@ -771,6 +743,10 @@ paths:
|
||||
- in: query
|
||||
name: is_active
|
||||
schema: { type: boolean }
|
||||
- in: query
|
||||
name: category_type
|
||||
description: Filter by category type (STOCK for Items module, ASSET for Assets module)
|
||||
schema: { type: string, enum: [STOCK, ASSET] }
|
||||
responses:
|
||||
"200":
|
||||
description: List fetched
|
||||
@ -982,75 +958,6 @@ paths:
|
||||
description: Deleted
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
"404": { description: Not found }
|
||||
/masters/brands:
|
||||
get:
|
||||
tags: [Brands]
|
||||
summary: List Brands
|
||||
parameters:
|
||||
- in: query
|
||||
name: page
|
||||
schema: { type: integer, default: 1 }
|
||||
- in: query
|
||||
name: limit
|
||||
schema: { type: integer, default: 20, maximum: 100 }
|
||||
- in: query
|
||||
name: search
|
||||
schema: { type: string }
|
||||
- in: query
|
||||
name: is_active
|
||||
schema: { type: boolean }
|
||||
responses:
|
||||
"200":
|
||||
description: List fetched
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
post:
|
||||
tags: [Brands]
|
||||
summary: Create Brand
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/BrandsCreateBody" }
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
"409": { description: Duplicate key }
|
||||
/masters/brands/{id}:
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema: { type: string }
|
||||
get:
|
||||
tags: [Brands]
|
||||
summary: Get Brand by id
|
||||
responses:
|
||||
"200":
|
||||
description: Fetched
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
"404": { description: Not found }
|
||||
put:
|
||||
tags: [Brands]
|
||||
summary: Update Brand
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/BrandsUpdateBody" }
|
||||
responses:
|
||||
"200":
|
||||
description: Updated
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
"404": { description: Not found }
|
||||
delete:
|
||||
tags: [Brands]
|
||||
summary: Delete Brand
|
||||
responses:
|
||||
"200":
|
||||
description: Deleted
|
||||
content: { application/json: { schema: { $ref: "#/components/schemas/ApiResponse" } } }
|
||||
"404": { description: Not found }
|
||||
/masters/gst-rates:
|
||||
get:
|
||||
tags: [GST Rates]
|
||||
|
||||
@ -19,17 +19,12 @@ components:
|
||||
remarks: { type: string, example: 'Urgent line' }
|
||||
PurchaseOrdersCreateBody:
|
||||
type: object
|
||||
required: [po_date, po_type, vendor_id, plant_id, items]
|
||||
required: [po_date, vendor_id, plant_id, items]
|
||||
properties:
|
||||
po_date: { type: string, format: date, example: '2026-06-18' }
|
||||
po_type:
|
||||
type: string
|
||||
enum: [RAW_MATERIAL, PACKING_MATERIAL, ASSET_CAPITAL, SERVICE, GENERAL]
|
||||
example: RAW_MATERIAL
|
||||
vendor_id: { type: integer, example: 1 }
|
||||
plant_id: { type: integer, example: 1 }
|
||||
warehouse_id: { type: integer, nullable: true, example: 1 }
|
||||
brand_id: { type: integer, nullable: true, example: 1 }
|
||||
payment_term_id: { type: integer, nullable: true, example: 1 }
|
||||
delivery_term_id: { type: integer, nullable: true, example: 1 }
|
||||
expected_delivery_date: { type: string, format: date, nullable: true, example: '2026-07-01' }
|
||||
@ -49,13 +44,9 @@ components:
|
||||
minProperties: 1
|
||||
properties:
|
||||
po_date: { type: string, format: date, example: '2026-06-18' }
|
||||
po_type:
|
||||
type: string
|
||||
enum: [RAW_MATERIAL, PACKING_MATERIAL, ASSET_CAPITAL, SERVICE, GENERAL]
|
||||
vendor_id: { type: integer, example: 1 }
|
||||
plant_id: { type: integer, example: 1 }
|
||||
warehouse_id: { type: integer, nullable: true }
|
||||
brand_id: { type: integer, nullable: true }
|
||||
payment_term_id: { type: integer, nullable: true }
|
||||
delivery_term_id: { type: integer, nullable: true }
|
||||
expected_delivery_date: { type: string, format: date, nullable: true }
|
||||
@ -107,7 +98,7 @@ paths:
|
||||
parameters:
|
||||
- { name: search, in: query, schema: { type: string, example: 'PO/2026' } }
|
||||
- { name: status, in: query, schema: { type: string, example: DRAFT } }
|
||||
- { name: po_type, in: query, schema: { type: string, example: RAW_MATERIAL } }
|
||||
- { name: vendor_type, in: query, schema: { type: string, example: RAW_MATERIAL } }
|
||||
- { name: vendor_id, in: query, schema: { type: integer, example: 1 } }
|
||||
- { name: plant_id, in: query, schema: { type: integer, example: 1 } }
|
||||
- { name: date_from, in: query, schema: { type: string, format: date } }
|
||||
@ -127,7 +118,7 @@ paths:
|
||||
- { name: limit, in: query, schema: { type: integer, example: 20 } }
|
||||
- { name: search, in: query, schema: { type: string, example: 'PO/2026' } }
|
||||
- { name: status, in: query, schema: { type: string, example: DRAFT } }
|
||||
- { name: po_type, in: query, schema: { type: string, example: RAW_MATERIAL } }
|
||||
- { name: vendor_type, in: query, schema: { type: string, example: RAW_MATERIAL } }
|
||||
- { name: vendor_id, in: query, schema: { type: integer, example: 1 } }
|
||||
- { name: plant_id, in: query, schema: { type: integer, example: 1 } }
|
||||
- { name: date_from, in: query, schema: { type: string, format: date } }
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
const asyncHandler = require('../../../utils/asyncHandler');
|
||||
const ApiResponse = require('../../../utils/ApiResponse');
|
||||
const service = require('./brands.service');
|
||||
|
||||
const create = asyncHandler(async (req, res) => {
|
||||
const data = await service.createBrands(req.body, req.user?.id, req.id);
|
||||
res.status(201).json(new ApiResponse(201, data, 'brands created successfully'));
|
||||
});
|
||||
|
||||
const list = asyncHandler(async (req, res) => {
|
||||
const result = await service.listBrands(req.query);
|
||||
res.json(new ApiResponse(200, result.data, 'brands list fetched', result.meta));
|
||||
});
|
||||
|
||||
const getOne = asyncHandler(async (req, res) => {
|
||||
const data = await service.getBrandsById(req.params.id);
|
||||
res.json(new ApiResponse(200, data, 'brands fetched'));
|
||||
});
|
||||
|
||||
const update = asyncHandler(async (req, res) => {
|
||||
const data = await service.updateBrands(req.params.id, req.body, req.user?.id, req.id);
|
||||
res.json(new ApiResponse(200, data, 'brands updated successfully'));
|
||||
});
|
||||
|
||||
const remove = asyncHandler(async (req, res) => {
|
||||
await service.deleteBrands(req.params.id, req.user?.id, req.id);
|
||||
res.json(new ApiResponse(200, null, 'brands deleted successfully'));
|
||||
});
|
||||
|
||||
const exportCsv = asyncHandler(async (req, res) => {
|
||||
const csv = await service.exportBrands(req.query);
|
||||
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="brands-export.csv"');
|
||||
res.send(csv);
|
||||
});
|
||||
|
||||
module.exports = { create, list, exportCsv, getOne, update, remove };
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
const express = require('express');
|
||||
const authenticate = require('../../../middlewares/auth.middleware');
|
||||
const authorize = require('../../../middlewares/rbac.middleware');
|
||||
const validate = require('../../../middlewares/validate.middleware');
|
||||
const controller = require('./brands.controller');
|
||||
const { createSchema, updateSchema, listQuerySchema, exportQuerySchema } = require('./brands.validation');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.use(authenticate);
|
||||
router.get('/', authorize('MASTERS', 'view'), validate(listQuerySchema, 'query'), controller.list);
|
||||
router.get(
|
||||
'/export',
|
||||
authorize('MASTERS', 'export'),
|
||||
validate(exportQuerySchema, 'query'),
|
||||
controller.exportCsv
|
||||
);
|
||||
router.get('/:id', authorize('MASTERS', 'view'), controller.getOne);
|
||||
router.post('/', authorize('MASTERS', 'create'), validate(createSchema), controller.create);
|
||||
router.put('/:id', authorize('MASTERS', 'edit'), validate(updateSchema), controller.update);
|
||||
router.delete('/:id', authorize('MASTERS', 'delete'), controller.remove);
|
||||
|
||||
module.exports = router;
|
||||
@ -1,75 +0,0 @@
|
||||
const { buildMasterService } = require('../_shared/master.factory');
|
||||
|
||||
const config = {
|
||||
modelName: 'brands',
|
||||
tableName: 'brands',
|
||||
uniqueField: 'code',
|
||||
softDelete: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'code',
|
||||
type: 'string',
|
||||
uppercase: true,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
uppercase: false,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'brand_type',
|
||||
type: 'string',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'contact_person',
|
||||
type: 'string',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
type: 'string',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
type: 'string',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'is_active',
|
||||
type: 'boolean',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'created_by',
|
||||
type: 'int',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'updated_by',
|
||||
type: 'int',
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const service = buildMasterService(config);
|
||||
|
||||
module.exports = {
|
||||
createBrands: service.createOne,
|
||||
listBrands: service.list,
|
||||
exportBrands: service.exportCsv,
|
||||
getBrandsById: service.getOne,
|
||||
updateBrands: service.updateOne,
|
||||
deleteBrands: service.removeOne,
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
const Joi = require('joi');
|
||||
const { masterCode, masterName, listQuerySchema, exportQuerySchema } = require('../_shared/masters.validation');
|
||||
|
||||
const BRAND_TYPES = ['OWN', 'OEM', 'THIRD_PARTY'];
|
||||
|
||||
const createSchema = Joi.object({
|
||||
code: masterCode({ max: 30, required: true }),
|
||||
name: masterName({ max: 150, required: true }),
|
||||
brand_type: Joi.string()
|
||||
.valid(...BRAND_TYPES)
|
||||
.default('OWN'),
|
||||
contact_person: masterName({ max: 100 }).allow(null),
|
||||
phone: Joi.string().max(20).allow(null, '').optional(),
|
||||
email: Joi.string().email().max(200).allow(null, '').optional(),
|
||||
is_active: Joi.boolean().default(true),
|
||||
});
|
||||
|
||||
const updateSchema = Joi.object({
|
||||
code: masterCode({ max: 30 }),
|
||||
name: masterName({ max: 150 }),
|
||||
brand_type: Joi.string().valid(...BRAND_TYPES).optional(),
|
||||
contact_person: masterName({ max: 100 }).allow(null),
|
||||
phone: Joi.string().max(20).allow(null, '').optional(),
|
||||
email: Joi.string().email().max(200).allow(null, '').optional(),
|
||||
is_active: Joi.boolean().optional(),
|
||||
}).min(1);
|
||||
|
||||
module.exports = { createSchema, updateSchema, listQuerySchema, exportQuerySchema, BRAND_TYPES };
|
||||
@ -1,10 +1,27 @@
|
||||
const { buildMasterService } = require('../_shared/master.factory');
|
||||
|
||||
const toDecimal = (value) => (value !== null && value !== undefined ? Number(value) : value);
|
||||
|
||||
const mapRow = (row) => {
|
||||
if (!row) return row;
|
||||
const { gst_rates, ...rest } = row;
|
||||
return {
|
||||
...rest,
|
||||
gst_rate: gst_rates
|
||||
? { ...gst_rates, rate_pct: toDecimal(gst_rates.rate_pct) }
|
||||
: null,
|
||||
};
|
||||
};
|
||||
|
||||
const config = {
|
||||
modelName: 'hsn_codes',
|
||||
tableName: 'hsn_codes',
|
||||
uniqueField: 'code',
|
||||
softDelete: false,
|
||||
include: {
|
||||
gst_rates: { select: { id: true, rate_pct: true, description: true } },
|
||||
},
|
||||
mapRow,
|
||||
fields: [
|
||||
{
|
||||
name: 'code',
|
||||
@ -18,6 +35,13 @@ const config = {
|
||||
uppercase: false,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'gst_rate_id',
|
||||
type: 'int',
|
||||
asBigInt: true,
|
||||
uppercase: false,
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
name: 'is_active',
|
||||
type: 'boolean',
|
||||
@ -25,6 +49,13 @@ const config = {
|
||||
searchable: false,
|
||||
},
|
||||
],
|
||||
exportColumns: [
|
||||
{ key: 'code', header: 'Code' },
|
||||
{ key: 'description', header: 'Description' },
|
||||
{ key: (row) => (row.gst_rate ? row.gst_rate.rate_pct : ''), header: 'GST %' },
|
||||
{ key: 'is_active', header: 'Is Active' },
|
||||
{ key: 'created_at', header: 'Created At', type: 'datetime' },
|
||||
],
|
||||
};
|
||||
|
||||
const service = buildMasterService(config);
|
||||
|
||||
@ -13,12 +13,14 @@ const hsnCodeField = Joi.string()
|
||||
const createSchema = Joi.object({
|
||||
code: hsnCodeField.required(),
|
||||
description: Joi.string().allow(null, '').optional(),
|
||||
gst_rate_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
is_active: Joi.boolean().optional(),
|
||||
});
|
||||
|
||||
const updateSchema = Joi.object({
|
||||
code: hsnCodeField.optional(),
|
||||
description: Joi.string().allow(null, '').optional(),
|
||||
gst_rate_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
is_active: Joi.boolean().optional(),
|
||||
}).min(1);
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ const router = express.Router();
|
||||
|
||||
router.use('/uom', require('./uom/uom.routes'));
|
||||
router.use('/item-categories', require('./item-categories/item-categories.routes'));
|
||||
router.use('/brands', require('./brands/brands.routes'));
|
||||
router.use('/gst-rates', require('./gst-rates/gst-rates.routes'));
|
||||
router.use('/hsn-codes', require('./hsn-codes/hsn-codes.routes'));
|
||||
router.use('/payment-terms', require('./payment-terms/payment-terms.routes'));
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
const CATEGORY_TYPES = ['STOCK', 'ASSET'];
|
||||
|
||||
module.exports = { CATEGORY_TYPES };
|
||||
@ -20,6 +20,13 @@ const config = {
|
||||
uppercase: false,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
name: 'category_type',
|
||||
type: 'string',
|
||||
uppercase: true,
|
||||
searchable: false,
|
||||
filterable: true,
|
||||
},
|
||||
{
|
||||
name: 'code_prefix',
|
||||
type: 'string',
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
const Joi = require('joi');
|
||||
const { masterCode, masterName, listQuerySchema, exportQuerySchema } = require('../_shared/masters.validation');
|
||||
const { masterCode, masterName, listQuerySchema } = require('../_shared/masters.validation');
|
||||
const { DEPRECIATION_METHODS } = require('../../assets/assets.constants');
|
||||
const { CATEGORY_TYPES } = require('./item-categories.constants');
|
||||
|
||||
const createSchema = Joi.object({
|
||||
code: masterCode({ max: 30 }),
|
||||
name: masterName({ max: 150 }),
|
||||
category_type: Joi.string()
|
||||
.uppercase()
|
||||
.valid(...CATEGORY_TYPES)
|
||||
.required(),
|
||||
code_prefix: masterCode({ max: 10 }).allow(null, ''),
|
||||
default_useful_life_years: Joi.number().integer().min(0).allow(null).optional(),
|
||||
default_depreciation_method: Joi.string()
|
||||
@ -17,6 +22,10 @@ const createSchema = Joi.object({
|
||||
const updateSchema = Joi.object({
|
||||
code: masterCode({ max: 30 }),
|
||||
name: masterName({ max: 150 }),
|
||||
category_type: Joi.string()
|
||||
.uppercase()
|
||||
.valid(...CATEGORY_TYPES)
|
||||
.optional(),
|
||||
code_prefix: masterCode({ max: 10 }).allow(null, ''),
|
||||
default_useful_life_years: Joi.number().integer().min(0).allow(null).optional(),
|
||||
default_depreciation_method: Joi.string()
|
||||
@ -26,4 +35,21 @@ const updateSchema = Joi.object({
|
||||
is_active: Joi.boolean().optional(),
|
||||
}).min(1);
|
||||
|
||||
module.exports = { createSchema, updateSchema, listQuerySchema, exportQuerySchema };
|
||||
const itemCategoriesListQuerySchema = listQuerySchema.keys({
|
||||
category_type: Joi.string()
|
||||
.uppercase()
|
||||
.valid(...CATEGORY_TYPES)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const exportQuerySchema = itemCategoriesListQuerySchema.keys({
|
||||
page: Joi.strip(),
|
||||
limit: Joi.strip(),
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
createSchema,
|
||||
updateSchema,
|
||||
listQuerySchema: itemCategoriesListQuerySchema,
|
||||
exportQuerySchema,
|
||||
};
|
||||
|
||||
@ -14,7 +14,6 @@ const SOFT_DELETE_TABLES = new Set([
|
||||
'item_categories',
|
||||
'item_subcategories',
|
||||
'uom',
|
||||
'brands',
|
||||
]);
|
||||
|
||||
const itemInclude = {
|
||||
@ -23,7 +22,6 @@ const itemInclude = {
|
||||
hsn_codes: { select: { id: true, code: true, description: true } },
|
||||
uom: { select: { id: true, code: true, name: true } },
|
||||
gst_rates: { select: { id: true, rate_pct: true, description: true } },
|
||||
brands: { select: { id: true, code: true, name: true } },
|
||||
};
|
||||
|
||||
const toDecimal = (value) =>
|
||||
@ -37,7 +35,6 @@ const sanitizeItem = (row) => {
|
||||
hsn_codes,
|
||||
uom,
|
||||
gst_rates,
|
||||
brands,
|
||||
...rest
|
||||
} = row;
|
||||
|
||||
@ -52,12 +49,10 @@ const sanitizeItem = (row) => {
|
||||
gst_rate: gst_rates
|
||||
? { ...gst_rates, rate_pct: toDecimal(gst_rates.rate_pct) }
|
||||
: null,
|
||||
brand: brands || null,
|
||||
item_categories: undefined,
|
||||
item_subcategories: undefined,
|
||||
hsn_codes: undefined,
|
||||
gst_rates: undefined,
|
||||
brands: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
@ -86,7 +81,6 @@ const normalizePayload = (payload, { isCreate = false } = {}) => {
|
||||
'uom_id',
|
||||
'hsn_code_id',
|
||||
'gst_rate_id',
|
||||
'brand_id',
|
||||
];
|
||||
for (const field of bigintFields) {
|
||||
if (data[field] !== undefined && data[field] !== null && data[field] !== '') {
|
||||
@ -169,9 +163,6 @@ const validateItemPayload = async (payload, { isCreate = false } = {}) => {
|
||||
if (payload.uom_id) await assertReference('uom', payload.uom_id, 'uom_id');
|
||||
if (payload.hsn_code_id !== undefined) await assertHsnCode(payload.hsn_code_id);
|
||||
if (payload.gst_rate_id !== undefined) await assertGstRate(payload.gst_rate_id);
|
||||
if (payload.brand_id) {
|
||||
await assertReference('brands', payload.brand_id, 'brand_id', { requireActive: false });
|
||||
}
|
||||
};
|
||||
|
||||
const createItems = async (payload, userId, requestId) => {
|
||||
@ -250,7 +241,6 @@ const exportItems = async (query) => {
|
||||
{ key: (row) => row.uom?.code || '', header: 'UOM' },
|
||||
{ key: (row) => row.hsn_code?.code || '', header: 'HSN Code' },
|
||||
{ key: (row) => (row.gst_rate ? row.gst_rate.rate_pct : ''), header: 'GST %' },
|
||||
{ key: (row) => row.brand?.name || '', header: 'Brand' },
|
||||
{ key: 'is_asset_item', header: 'Is Asset Item' },
|
||||
{ key: 'is_active', header: 'Is Active' },
|
||||
{ key: 'created_at', header: 'Created At', type: 'datetime' },
|
||||
|
||||
@ -8,7 +8,6 @@ const createSchema = Joi.object({
|
||||
uom_id: Joi.number().integer().positive().required(),
|
||||
hsn_code_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
gst_rate_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
brand_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
is_asset_item: Joi.boolean().default(false),
|
||||
description: Joi.string().allow(null, '').optional(),
|
||||
specification: Joi.string().allow(null, '').optional(),
|
||||
@ -24,7 +23,6 @@ const updateSchema = Joi.object({
|
||||
uom_id: Joi.number().integer().positive().optional(),
|
||||
hsn_code_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
gst_rate_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
brand_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
is_asset_item: Joi.boolean().optional(),
|
||||
description: Joi.string().allow(null, '').optional(),
|
||||
specification: Joi.string().allow(null, '').optional(),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
const PO_TYPES = ['RAW_MATERIAL', 'PACKING_MATERIAL', 'ASSET_CAPITAL', 'SERVICE', 'GENERAL'];
|
||||
const VENDOR_TYPES = ['RAW_MATERIAL', 'PACKING_MATERIAL', 'ASSET_CAPITAL', 'SERVICE', 'GENERAL'];
|
||||
|
||||
const PO_STATUSES = [
|
||||
'DRAFT',
|
||||
@ -26,7 +26,7 @@ const AMENDABLE_STATUSES = ['APPROVED', 'SENT_TO_VENDOR', 'PARTIALLY_RECEIVED'];
|
||||
const DELETABLE_STATUSES = ['DRAFT', 'REJECTED'];
|
||||
|
||||
module.exports = {
|
||||
PO_TYPES,
|
||||
VENDOR_TYPES,
|
||||
PO_STATUSES,
|
||||
EDITABLE_STATUSES,
|
||||
SUBMITTABLE_STATUSES,
|
||||
|
||||
@ -22,10 +22,9 @@ const { assertPlant, assertWarehouse } = require('../../utils/locations');
|
||||
const { sanitizeAttachment } = require('./po.attachments.service');
|
||||
|
||||
const poListInclude = {
|
||||
vendors: { select: { id: true, vendor_code: true, vendor_name: true } },
|
||||
vendors: { select: { id: true, vendor_code: true, vendor_name: true, vendor_type: true } },
|
||||
plant: { select: { id: true, code: true, name: true } },
|
||||
warehouse: { select: { id: true, code: true, name: true } },
|
||||
brands: { select: { id: true, code: true, name: true } },
|
||||
users_purchase_orders_created_byTousers: { select: { id: true, full_name: true } },
|
||||
};
|
||||
|
||||
@ -66,6 +65,7 @@ const poPdfInclude = {
|
||||
id: true,
|
||||
vendor_code: true,
|
||||
vendor_name: true,
|
||||
vendor_type: true,
|
||||
gstin: true,
|
||||
vendor_addresses: {
|
||||
where: { is_active: true },
|
||||
@ -108,7 +108,6 @@ const sanitizePo = (po) => {
|
||||
vendors,
|
||||
plant,
|
||||
warehouse,
|
||||
brands,
|
||||
payment_terms,
|
||||
delivery_terms,
|
||||
users_purchase_orders_created_byTousers,
|
||||
@ -125,7 +124,6 @@ const sanitizePo = (po) => {
|
||||
vendor: vendors || null,
|
||||
plant: plant || null,
|
||||
warehouse: warehouse || null,
|
||||
brand: brands || null,
|
||||
payment_term: payment_terms || null,
|
||||
delivery_term: delivery_terms || null,
|
||||
created_by_user: users_purchase_orders_created_byTousers || null,
|
||||
@ -155,7 +153,6 @@ const sanitizePo = (po) => {
|
||||
vendors: undefined,
|
||||
plants: undefined,
|
||||
warehouses: undefined,
|
||||
brands: undefined,
|
||||
payment_terms: undefined,
|
||||
delivery_terms: undefined,
|
||||
users_purchase_orders_created_byTousers: undefined,
|
||||
@ -259,8 +256,6 @@ const buildHeaderData = async (payload, builtItems, userId) => {
|
||||
await assertReference('vendors', payload.vendor_id, 'vendor_id');
|
||||
await assertPlant(payload.plant_id, 'plant_id');
|
||||
if (payload.warehouse_id) await assertWarehouse(payload.warehouse_id, 'warehouse_id');
|
||||
if (payload.brand_id)
|
||||
await assertReference('brands', payload.brand_id, 'brand_id', { requireActive: false });
|
||||
if (payload.payment_term_id)
|
||||
await assertReference('payment_terms', payload.payment_term_id, 'payment_term_id');
|
||||
if (payload.delivery_term_id)
|
||||
@ -283,11 +278,9 @@ const buildHeaderData = async (payload, builtItems, userId) => {
|
||||
|
||||
return {
|
||||
po_date: toDateOnly(payload.po_date),
|
||||
po_type: payload.po_type,
|
||||
vendor_id: BigInt(payload.vendor_id),
|
||||
plant_id: BigInt(payload.plant_id),
|
||||
warehouse_id: payload.warehouse_id ? BigInt(payload.warehouse_id) : null,
|
||||
brand_id: payload.brand_id ? BigInt(payload.brand_id) : null,
|
||||
payment_term_id: payload.payment_term_id ? BigInt(payload.payment_term_id) : null,
|
||||
delivery_term_id: payload.delivery_term_id ? BigInt(payload.delivery_term_id) : null,
|
||||
expected_delivery_date: payload.expected_delivery_date
|
||||
@ -349,7 +342,7 @@ const buildPoPdfPayload = (po, company) => {
|
||||
po_date: po.po_date,
|
||||
expected_delivery_date: po.expected_delivery_date,
|
||||
status: humanizeLabel(po.status),
|
||||
po_type: humanizeLabel(po.po_type),
|
||||
vendor_type: humanizeLabel(po.vendor?.vendor_type),
|
||||
revision_no: po.revision_no ?? 0,
|
||||
payment_term: po.payment_term?.name || null,
|
||||
delivery_term: po.delivery_term?.name || null,
|
||||
@ -371,7 +364,6 @@ const buildPoPdfPayload = (po, company) => {
|
||||
state: po.plant?.state || '',
|
||||
pincode: po.plant?.pincode || '',
|
||||
},
|
||||
brand: { name: po.brand?.name || '-' },
|
||||
warehouse: { name: po.warehouse?.name || '-' },
|
||||
items: (po.items || []).map((line) => {
|
||||
const orderedQty = toNum(line.ordered_qty);
|
||||
@ -433,8 +425,8 @@ const createPurchaseOrder = async (payload, userId, requestId) => {
|
||||
const buildPurchaseOrdersWhere = (query) => ({
|
||||
deleted_at: null,
|
||||
...(query.status ? { status: query.status } : {}),
|
||||
...(query.po_type ? { po_type: query.po_type } : {}),
|
||||
...(query.vendor_id ? { vendor_id: BigInt(query.vendor_id) } : {}),
|
||||
...(query.vendor_type ? { vendors: { vendor_type: query.vendor_type } } : {}),
|
||||
...(query.plant_id ? { plant_id: BigInt(query.plant_id) } : {}),
|
||||
...(query.search ? { po_number: { contains: query.search, mode: 'insensitive' } } : {}),
|
||||
...(query.date_from || query.date_to
|
||||
@ -476,14 +468,13 @@ const exportPurchaseOrders = async (query) => {
|
||||
[
|
||||
{ key: 'po_number', header: 'PO Number' },
|
||||
{ key: 'po_date', header: 'PO Date', type: 'date' },
|
||||
{ key: 'po_type', header: 'Type' },
|
||||
{ key: (row) => row.vendor?.vendor_type || '', header: 'Vendor Type' },
|
||||
{ key: 'status', header: 'Status' },
|
||||
{ key: 'revision_no', header: 'Revision' },
|
||||
{ key: (row) => row.vendor?.vendor_code || '', header: 'Vendor Code' },
|
||||
{ key: (row) => row.vendor?.vendor_name || '', header: 'Vendor Name' },
|
||||
{ key: (row) => row.plant?.name || '', header: 'Plant' },
|
||||
{ key: (row) => row.warehouse?.name || '', header: 'Warehouse' },
|
||||
{ key: (row) => row.brand?.name || '', header: 'Brand' },
|
||||
{ key: 'expected_delivery_date', header: 'Expected Delivery', type: 'date' },
|
||||
{ key: 'sub_total', header: 'Sub Total' },
|
||||
{ key: 'tax_total', header: 'Tax Total' },
|
||||
@ -504,11 +495,9 @@ const updatePurchaseOrder = async (id, payload, userId, requestId) => {
|
||||
|
||||
const merged = {
|
||||
po_date: payload.po_date ?? existing.po_date,
|
||||
po_type: payload.po_type ?? existing.po_type,
|
||||
vendor_id: payload.vendor_id ?? existing.vendor_id,
|
||||
plant_id: payload.plant_id ?? existing.plant_id,
|
||||
warehouse_id: payload.warehouse_id !== undefined ? payload.warehouse_id : existing.warehouse_id,
|
||||
brand_id: payload.brand_id !== undefined ? payload.brand_id : existing.brand_id,
|
||||
payment_term_id:
|
||||
payload.payment_term_id !== undefined ? payload.payment_term_id : existing.payment_term_id,
|
||||
delivery_term_id:
|
||||
@ -775,11 +764,9 @@ const amendPurchaseOrder = async (id, payload, userId, requestId) => {
|
||||
|
||||
const merged = {
|
||||
po_date: payload.po_date ?? existing.po_date,
|
||||
po_type: payload.po_type ?? existing.po_type,
|
||||
vendor_id: payload.vendor_id ?? existing.vendor_id,
|
||||
plant_id: payload.plant_id ?? existing.plant_id,
|
||||
warehouse_id: payload.warehouse_id !== undefined ? payload.warehouse_id : existing.warehouse_id,
|
||||
brand_id: payload.brand_id !== undefined ? payload.brand_id : existing.brand_id,
|
||||
payment_term_id:
|
||||
payload.payment_term_id !== undefined ? payload.payment_term_id : existing.payment_term_id,
|
||||
delivery_term_id:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const Joi = require('joi');
|
||||
const { PO_TYPES, PO_STATUSES } = require('./purchase-orders.constants');
|
||||
const { PO_STATUSES, VENDOR_TYPES } = require('./purchase-orders.constants');
|
||||
|
||||
const poItemSchema = Joi.object({
|
||||
item_id: Joi.number().integer().positive().required(),
|
||||
@ -16,13 +16,9 @@ const poItemSchema = Joi.object({
|
||||
|
||||
const poHeaderFields = {
|
||||
po_date: Joi.date().iso().required(),
|
||||
po_type: Joi.string()
|
||||
.valid(...PO_TYPES)
|
||||
.required(),
|
||||
vendor_id: Joi.number().integer().positive().required(),
|
||||
plant_id: Joi.number().integer().positive().required(),
|
||||
warehouse_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
brand_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
payment_term_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
delivery_term_id: Joi.number().integer().positive().allow(null).optional(),
|
||||
expected_delivery_date: Joi.date().iso().allow(null).optional(),
|
||||
@ -51,11 +47,9 @@ const createPurchaseOrderSchema = Joi.object({
|
||||
|
||||
const updatePurchaseOrderSchema = Joi.object({
|
||||
po_date: poHeaderFields.po_date.optional(),
|
||||
po_type: poHeaderFields.po_type.optional(),
|
||||
vendor_id: poHeaderFields.vendor_id.optional(),
|
||||
plant_id: poHeaderFields.plant_id.optional(),
|
||||
warehouse_id: poHeaderFields.warehouse_id.optional(),
|
||||
brand_id: poHeaderFields.brand_id.optional(),
|
||||
payment_term_id: poHeaderFields.payment_term_id.optional(),
|
||||
delivery_term_id: poHeaderFields.delivery_term_id.optional(),
|
||||
expected_delivery_date: poHeaderFields.expected_delivery_date.optional(),
|
||||
@ -72,11 +66,9 @@ const updatePurchaseOrderSchema = Joi.object({
|
||||
|
||||
const amendPurchaseOrderSchema = Joi.object({
|
||||
po_date: poHeaderFields.po_date.optional(),
|
||||
po_type: poHeaderFields.po_type.optional(),
|
||||
vendor_id: poHeaderFields.vendor_id.optional(),
|
||||
plant_id: poHeaderFields.plant_id.optional(),
|
||||
warehouse_id: poHeaderFields.warehouse_id.optional(),
|
||||
brand_id: poHeaderFields.brand_id.optional(),
|
||||
payment_term_id: poHeaderFields.payment_term_id.optional(),
|
||||
delivery_term_id: poHeaderFields.delivery_term_id.optional(),
|
||||
expected_delivery_date: poHeaderFields.expected_delivery_date.optional(),
|
||||
@ -98,8 +90,8 @@ const listPurchaseOrdersQuerySchema = Joi.object({
|
||||
status: Joi.string()
|
||||
.valid(...PO_STATUSES)
|
||||
.optional(),
|
||||
po_type: Joi.string()
|
||||
.valid(...PO_TYPES)
|
||||
vendor_type: Joi.string()
|
||||
.valid(...VENDOR_TYPES)
|
||||
.optional(),
|
||||
vendor_id: Joi.number().integer().positive().optional(),
|
||||
plant_id: Joi.number().integer().positive().optional(),
|
||||
|
||||
@ -8,12 +8,10 @@ const PG_CODES = {
|
||||
};
|
||||
|
||||
const CONSTRAINT_MESSAGES = {
|
||||
brands_brand_type_check: 'Invalid brand type. Allowed values: OWN, OEM, THIRD_PARTY.',
|
||||
item_categories_category_type_check: 'Invalid category type. Allowed values: STOCK, ASSET.',
|
||||
};
|
||||
|
||||
const TABLE_MESSAGES = {
|
||||
brands: 'Invalid brand data. Please check required fields and allowed values.',
|
||||
};
|
||||
const TABLE_MESSAGES = {};
|
||||
|
||||
const extractPgCode = (err) => {
|
||||
const fromCause = err?.cause?.code;
|
||||
|
||||
@ -18,7 +18,7 @@ const getDummyPoData = () => ({
|
||||
po_date: '2026-07-07',
|
||||
expected_delivery_date: '2026-07-21',
|
||||
status: 'Approved',
|
||||
po_type: 'Raw material',
|
||||
vendor_type: 'Raw material',
|
||||
revision_no: 1,
|
||||
payment_term: '30 days credit',
|
||||
delivery_term: 'FOB (freight on board)',
|
||||
@ -41,7 +41,6 @@ const getDummyPoData = () => ({
|
||||
state: 'Tamil Nadu',
|
||||
pincode: '600032',
|
||||
},
|
||||
brand: { name: 'Tata Tiscon' },
|
||||
warehouse: { name: 'Main warehouse' },
|
||||
items: [
|
||||
{
|
||||
@ -122,7 +121,6 @@ const generatePoHtml = (inputData = getDummyPoData()) => {
|
||||
const po = data.po || {};
|
||||
const vendor = data.vendor || {};
|
||||
const shipTo = data.ship_to || {};
|
||||
const brand = data.brand || {};
|
||||
const warehouse = data.warehouse || {};
|
||||
const totals = data.totals || {};
|
||||
|
||||
@ -471,12 +469,8 @@ const generatePoHtml = (inputData = getDummyPoData()) => {
|
||||
|
||||
<div class="class-row">
|
||||
<div>
|
||||
<div class="label">PO type</div>
|
||||
<div class="value">${escapeHtml(po.po_type || '-')}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Brand</div>
|
||||
<div class="value">${escapeHtml(brand.name || '-')}</div>
|
||||
<div class="label">Vendor type</div>
|
||||
<div class="value">${escapeHtml(po.vendor_type || '-')}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Warehouse</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user