diff --git a/server/AyaNova/models/QuoteItem.cs b/server/AyaNova/models/QuoteItem.cs index fcf92b71..7787e2c4 100644 --- a/server/AyaNova/models/QuoteItem.cs +++ b/server/AyaNova/models/QuoteItem.cs @@ -1,43 +1,86 @@ +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; using AyaNova.Biz; + namespace AyaNova.Models { - //NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal, - //otherwise the server will call it an invalid record if the field isn't sent from client - + public class QuoteItem : ICoreBizObjectModel { - public long Id { get; set; } - public uint Concurrency { get; set; } - - [Required] - public string Name { get; set; } - public bool Active { get; set; } - public string Notes { get; set; } - public string Wiki {get;set;} - public string CustomFields { get; set; } - public List Tags { get; set; } - - //Principle - [Required]//this required annotation should cause a cascade delete to happen automatically when wo is deleted, need to test that - public long QuoteId { get; set; }//fk - public Quote Quote { get; set; } - - //Dependents - - public QuoteItem() - { - Tags = new List(); - } - - [NotMapped, JsonIgnore] + [NotMapped, JsonIgnore] public AyaType AyaType { get => AyaType.QuoteItem; } + public long Id { get; set; } + public uint Concurrency { get; set; } + public string Notes { get; set; }//"Summary" field + public string Wiki { get; set; } + public string CustomFields { get; set; } + public List Tags { get; set; } = new List(); + + [Required] + public long QuoteId { get; set; } + public string TechNotes { get; set; } + public long? QuoteItemStatusId { get; set; } + public long? QuoteItemPriorityId { get; set; } + public DateTime? RequestDate { get; set; } + public bool WarrantyService { get; set; } = false; + public int Sequence { get; set; } + + //workaround for notification + [NotMapped, JsonIgnore] + public string Name { get; set; } + + //Principle + [JsonIgnore] + public Quote Quote { get; set; } + //dependents + public List Expenses { get; set; } = new List(); + public List Labors { get; set; } = new List(); + public List Loans { get; set; } = new List(); + public List Parts { get; set; } = new List(); + public List ScheduledUsers { get; set; } = new List(); + public List Tasks { get; set; } = new List(); + public List Travels { get; set; } = new List(); + public List Units { get; set; } = new List(); + public List OutsideServices { get; set; } = new List(); + }//eoc }//eons + + +/* + +CREATE TABLE [dbo].[AQuoteITEM]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteID] [uniqueidentifier] NOT NULL, + [ACREATOR] [uniqueidentifier] NOT NULL, + [AMODIFIER] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NOT NULL, + [AMODIFIED] [datetime] NOT NULL, + [ATECHNOTES] [ntext] NULL, + [AQuoteSTATUSID] [uniqueidentifier] NULL, + [APRIORITYID] [uniqueidentifier] NULL, + [AREQUESTDATE] [datetime] NULL, + [ASUMMARY] [nvarchar](255) NULL,//Now Notes + [ATYPEID] [uniqueidentifier] NULL,//Now a tag + [AUNITID] [uniqueidentifier] NULL,//MOVED TO WOITEMUNITS COLLECTION + [AQuoteITEMUNITSERVICETYPEID] [uniqueidentifier] NULL,//MOVE TO WOITEMUNITS COLLECTION? + [AWARRANTYSERVICE] [bit] NOT NULL, + [ACUSTOM1] [ntext] NULL, + [ACUSTOM2] [ntext] NULL, + [ACUSTOM3] [ntext] NULL, + [ACUSTOM4] [ntext] NULL, + [ACUSTOM5] [ntext] NULL, + [ACUSTOM6] [ntext] NULL, + [ACUSTOM7] [ntext] NULL, + [ACUSTOM8] [ntext] NULL, + [ACUSTOM9] [ntext] NULL, + [ACUSTOM0] [ntext] NULL + +*/ \ No newline at end of file diff --git a/server/AyaNova/models/QuoteItemExpense.cs b/server/AyaNova/models/QuoteItemExpense.cs new file mode 100644 index 00000000..aeb588d3 --- /dev/null +++ b/server/AyaNova/models/QuoteItemExpense.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using AyaNova.Biz; + +namespace AyaNova.Models +{ + public class QuoteItemExpense : ICoreBizObjectModel + { + + public long Id { get; set; } + public uint Concurrency { get; set; } + + public string Description { get; set; } + public string Name { get; set; } + [Required] + public decimal TotalCost { get; set; } + [Required] + public decimal ChargeAmount { get; set; } + [Required] + public decimal TaxPaid { get; set; } + public long? ChargeTaxCodeId { get; set; } + [NotMapped] + public string TaxCodeViz { get; set; } + + public bool ReimburseUser { get; set; } = false; + public long? UserId { get; set; } + [NotMapped] + public string UserViz { get; set; } + public bool ChargeToCustomer { get; set; } = false; + + [NotMapped] + public decimal TaxAViz { get; set; } + [NotMapped] + public decimal TaxBViz { get; set; } + [NotMapped] + public decimal LineTotalViz { get; set; } + + + + [Required] + public long QuoteItemId { get; set; } + [JsonIgnore] + public QuoteItem QuoteItem { get; set; } + + //workaround for notification + [NotMapped, JsonIgnore] + public List Tags { get; set; } = new List(); + + + [NotMapped, JsonIgnore] + public AyaType AyaType { get => AyaType.QuoteItemExpense; } + + }//eoc +}//eons +/* +[dbo].[AQuoteITEMMISCEXPENSE]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteITEMID] [uniqueidentifier] NOT NULL, + [ACREATOR] [uniqueidentifier] NOT NULL, + [AMODIFIER] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NOT NULL, + [AMODIFIED] [datetime] NOT NULL, + [ATOTALCOST] [decimal](19, 5) NULL, + [ACHARGEAMOUNT] [decimal](19, 5) NULL, + [ADESCRIPTION] [nvarchar](255) NULL, + [ATAXPAID] [decimal](19, 5) NULL, + [ACHARGETAXCODEID] [uniqueidentifier] NULL, + [ANAME] [nvarchar](255) NULL, + [AREIMBURSEUSER] [bit] NOT NULL, + [AUSERID] [uniqueidentifier] NULL, + [ACHARGETOCLIENT] [bit] NOT NULL, +*/ \ No newline at end of file diff --git a/server/AyaNova/models/QuoteItemLabor.cs b/server/AyaNova/models/QuoteItemLabor.cs new file mode 100644 index 00000000..d4adeb7f --- /dev/null +++ b/server/AyaNova/models/QuoteItemLabor.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using AyaNova.Biz; + +namespace AyaNova.Models +{ + public class QuoteItemLabor : ICoreBizObjectModel + { + + public long Id { get; set; } + public uint Concurrency { get; set; } + + public long? UserId { get; set; } + [NotMapped] + public string UserViz { get; set; } + public DateTime? ServiceStartDate { get; set; } + public DateTime? ServiceStopDate { get; set; } + public long? ServiceRateId { get; set; } + [NotMapped] + public string ServiceRateViz { get; set; } + public string ServiceDetails { get; set; } + [Required] + public decimal ServiceRateQuantity { get; set; } + [Required] + public decimal NoChargeQuantity { get; set; } + //public long? ServiceBankId { get; set; } + public long? TaxCodeSaleId { get; set; } + [NotMapped] + public string TaxCodeViz { get; set; } + + + //Standard pricing fields (mostly to support printed reports though some show in UI) + //some not to be sent with record depending on role (i.e. cost and charge in some cases) + public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero + [NotMapped] + public decimal CostViz { get; set; }//cost from source record (e.g. serviceRate) or zero if no cost entered + [NotMapped] + public decimal ListPriceViz { get; set; }//List price from source record (e.g. serviceRate) or zero if no cost entered + [NotMapped] + public string UnitOfMeasureViz { get; set; }//"each", "hour" etc + [NotMapped] + public decimal PriceViz { get; set; }//per unit price used in calcs after discounts or manual price if non-null or just ListPrice if no discount or manual override + [NotMapped] + public decimal NetViz { get; set; }//quantity * price (before taxes line total essentially) + [NotMapped] + public decimal TaxAViz { get; set; }//total amount of taxA + [NotMapped] + public decimal TaxBViz { get; set; }//total amount of taxB + [NotMapped] + public decimal LineTotalViz { get; set; }//line total netViz + taxes + + + [Required] + public long QuoteItemId { get; set; } + [JsonIgnore] + public QuoteItem QuoteItem { get; set; } + + [NotMapped, JsonIgnore] + public AyaType AyaType { get => AyaType.QuoteItemLabor; } + + //workaround for notification + [NotMapped, JsonIgnore] + public List Tags { get; set; } = new List(); + [NotMapped, JsonIgnore] + public string Name { get; set; } + + }//eoc +}//eons + +/* +CREATE TABLE [dbo].[AQuoteITEMLABOR]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteITEMID] [uniqueidentifier] NOT NULL, + [ACREATOR] [uniqueidentifier] NOT NULL, + [AMODIFIER] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NOT NULL, + [AMODIFIED] [datetime] NOT NULL, + [AUSERID] [uniqueidentifier] NULL, + [ASERVICESTARTDATE] [datetime] NULL, + [ASERVICESTOPDATE] [datetime] NULL, + [ASERVICERATEID] [uniqueidentifier] NULL, + [ASERVICEDETAILS] [ntext] NULL, + [ASERVICERATEQUANTITY] [decimal](19, 5) NULL, + [ANOCHARGEQUANTITY] [decimal](19, 5) NULL, + [ASERVICEBANKID] [uniqueidentifier] NULL, + [ATAXRATESALEID] [uniqueidentifier] NULL +*/ \ No newline at end of file diff --git a/server/AyaNova/models/QuoteItemLoan.cs b/server/AyaNova/models/QuoteItemLoan.cs new file mode 100644 index 00000000..b98f3a33 --- /dev/null +++ b/server/AyaNova/models/QuoteItemLoan.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using AyaNova.Biz; + + +namespace AyaNova.Models +{ + public class QuoteItemLoan : ICoreBizObjectModel + { + public long Id { get; set; } + public uint Concurrency { get; set; } + public string Notes { get; set; } + public DateTime? OutDate { get; set; } + public DateTime? DueDate { get; set; } + public DateTime? ReturnDate { get; set; } + // [Required] + // public decimal Charges { get; set; }//removed in favor of ListPRice snapshot which normalizes fields to other objects + public long? TaxCodeId { get; set; } + [NotMapped] + public string TaxCodeViz { get; set; } + [Required] + public long LoanUnitId { get; set; } + [NotMapped] + public string LoanUnitViz { get; set; } + [Required] + public decimal Quantity { get; set; } + [Required] + public LoanUnitRateUnit Rate { get; set; } + + public decimal Cost { get; set; }//cost from source record (e.g. serviceRate) or zero if no cost entered + public decimal ListPrice { get; set; }//List price from source record (e.g. serviceRate) or zero if no cost entered + + //Standard pricing fields (mostly to support printed reports though some show in UI) + //some not to be sent with record depending on role (i.e. cost and charge in some cases) + public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero + + + [NotMapped] + public string UnitOfMeasureViz { get; set; }//"each", "hour" etc + [NotMapped] + public decimal PriceViz { get; set; }//per unit price used in calcs after discounts or manual price if non-null or just ListPrice if no discount or manual override + [NotMapped] + public decimal NetViz { get; set; }//quantity * price (before taxes line total essentially) + [NotMapped] + public decimal TaxAViz { get; set; }//total amount of taxA + [NotMapped] + public decimal TaxBViz { get; set; }//total amount of taxB + [NotMapped] + public decimal LineTotalViz { get; set; }//line total netViz + taxes + + //workaround for notification + [NotMapped, JsonIgnore] + public List Tags { get; set; } = new List(); + [NotMapped, JsonIgnore] + public string Name { get; set; } + + [Required] + public long QuoteItemId { get; set; } + [JsonIgnore] + public QuoteItem QuoteItem { get; set; } + + [NotMapped, JsonIgnore] + public AyaType AyaType { get => AyaType.QuoteItemLoan; } + + }//eoc +}//eons +/* +CREATE TABLE [dbo].[AQuoteITEMLOAN]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteITEMID] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NULL, + [AMODIFIED] [datetime] NULL, + [ACREATOR] [uniqueidentifier] NULL, + [AMODIFIER] [uniqueidentifier] NULL, + [ANOTES] [ntext] NULL, + [AOUTDATE] [datetime] NULL, + [ADUEDATE] [datetime] NULL, + [ARETURNDATE] [datetime] NULL, + [ACHARGES] [decimal](19, 5) NOT NULL, + [ATAXCODEID] [uniqueidentifier] NULL, + [ALOANITEMID] [uniqueidentifier] NOT NULL, + [AQUANTITY] [decimal](19, 5) NOT NULL, + [ARATE] [smallint] NOT NULL +*/ \ No newline at end of file diff --git a/server/AyaNova/models/QuoteItemPart.cs b/server/AyaNova/models/QuoteItemPart.cs new file mode 100644 index 00000000..aeb52dcf --- /dev/null +++ b/server/AyaNova/models/QuoteItemPart.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using AyaNova.Biz; + +namespace AyaNova.Models +{ + public class QuoteItemPart : ICoreBizObjectModel + { + + public long Id { get; set; } + public uint Concurrency { get; set; } + public string Description { get; set; } + public string Serials { get; set; } + [Required] + public long PartId { get; set; } + [NotMapped] + public string PartViz { get; set; } + [NotMapped] + public string PartNameViz { get; set; } + [NotMapped] + public string UpcViz { get; set; } + [Required] + public long PartWarehouseId { get; set; } + [NotMapped] + public string PartWarehouseViz { get; set; } + [Required] + public decimal Quantity { get; set; } + public long? TaxPartSaleId { get; set; } + [NotMapped] + public string TaxCodeViz { get; set; } + + //NOTE: part prices are volatile and expected to be frequently edited so snapshotted when newly added unlike other things like rates etc that are protected from change + public decimal Cost { get; set; }//cost from source record (e.g. serviceRate) or zero if no cost entered + public decimal ListPrice { get; set; }//List price from source record (e.g. serviceRate) or zero if no cost entered + + //Standard pricing fields (mostly to support printed reports though some show in UI) + //some not to be sent with record depending on role (i.e. cost and charge in some cases) + public decimal? PriceOverride { get; set; }//user entered manually overridden price, if null then ignored in calcs otherwise this *is* the price even if zero + + + [NotMapped] + public string UnitOfMeasureViz { get; set; }//"each", "hour" etc + [NotMapped] + public decimal PriceViz { get; set; }//per unit price used in calcs after discounts or manual price if non-null or just ListPrice if no discount or manual override + [NotMapped] + public decimal NetViz { get; set; }//quantity * price (before taxes line total essentially) + [NotMapped] + public decimal TaxAViz { get; set; }//total amount of taxA + [NotMapped] + public decimal TaxBViz { get; set; }//total amount of taxB + [NotMapped] + public decimal LineTotalViz { get; set; }//line total netViz + taxes + + //workaround for notification + [NotMapped, JsonIgnore] + public List Tags { get; set; } = new List(); + [NotMapped, JsonIgnore] + public string Name { get; set; } + + [Required] + public long QuoteItemId { get; set; } + [JsonIgnore] + public QuoteItem QuoteItem { get; set; } + + [NotMapped, JsonIgnore] + public AyaType AyaType { get => AyaType.QuoteItemPart; } + + }//eoc +}//eons + +/* +CREATE TABLE [dbo].[AQuoteITEMPART]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteITEMID] [uniqueidentifier] NOT NULL, + [ACREATOR] [uniqueidentifier] NOT NULL, + [AMODIFIER] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NOT NULL, + [AMODIFIED] [datetime] NOT NULL, + [APARTSERIALID] [uniqueidentifier] NULL,//DROP REPLACE WITH SERIALS text field same as whatever is done with POITEM + [APARTID] [uniqueidentifier] NULL, + [AQUANTITY] [decimal](19, 5) NULL,//CHANGE TO NOT NULL DEFAULT 0 + [ACOST] [decimal](19, 5) NULL, + [APRICE] [decimal](19, 5) NULL, + [ADISCOUNT] [decimal](19, 5) NULL, + [ADISCOUNTTYPE] [smallint] NULL,//DROP WAS NEVER USED IN V7 + [APARTWAREHOUSEID] [uniqueidentifier] NULL, + [ADESCRIPTION] [nvarchar](255) NULL, + [AUSED] [bit] NOT NULL,//DROP True = Part has been consumed False = Part is only "suggested", not actually consumed yet (used with quantityreserved) + [AHASAFFECTEDINVENTORY] [bit] NOT NULL,//DROP, now every save will affect inventory immediately + [ATAXPARTSALEID] [uniqueidentifier] NULL, + [AQUANTITYRESERVED] [decimal](19, 5) NULL //DROP, case 3789 due to immediately affecting inventory changes before would reserve separately, now will remove from inventory immediately or generate a request if insufficient +*/ \ No newline at end of file diff --git a/server/AyaNova/models/QuoteItemScheduledUser.cs b/server/AyaNova/models/QuoteItemScheduledUser.cs new file mode 100644 index 00000000..0828912e --- /dev/null +++ b/server/AyaNova/models/QuoteItemScheduledUser.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using AyaNova.Biz; + +namespace AyaNova.Models +{ + public class QuoteItemScheduledUser : ICoreBizObjectModel + { + public long Id { get; set; } + public uint Concurrency { get; set; } + public long? UserId { get; set; } + [NotMapped] + public string UserViz { get; set; } + public decimal EstimatedQuantity { get; set; } + public DateTime? StartDate { get; set; } + public DateTime? StopDate { get; set; } + public long? ServiceRateId { get; set; } + [NotMapped] + public string ServiceRateViz { get; set; } + + + //workaround for notification + [NotMapped, JsonIgnore] + public List Tags { get; set; } = new List(); + [NotMapped, JsonIgnore] + public string Name { get; set; } + + [Required] + public long QuoteItemId { get; set; } + [JsonIgnore] + public QuoteItem QuoteItem { get; set; } + [NotMapped, JsonIgnore] + public AyaType AyaType { get => AyaType.QuoteItemScheduledUser; } + }//eoc +}//eons +/* +CREATE TABLE [dbo].[AQuoteITEMSCHEDULEDUSER]( + [AID] [uniqueidentifier] NOT NULL, + [AQuoteITEMID] [uniqueidentifier] NOT NULL, + [ACREATOR] [uniqueidentifier] NOT NULL, + [AMODIFIER] [uniqueidentifier] NOT NULL, + [ACREATED] [datetime] NOT NULL, + [AMODIFIED] [datetime] NOT NULL, + [AUSERID] [uniqueidentifier] NULL, + [AESTIMATEDQUANTITY] [decimal](19, 5) NULL, + [ASTARTDATE] [datetime] NULL, + [ASTOPDATE] [datetime] NULL, + [ASERVICERATEID] [uniqueidentifier] NULL +*/ \ No newline at end of file diff --git a/server/AyaNova/util/Seeder.cs b/server/AyaNova/util/Seeder.cs index 3c0c61b4..432bcca9 100644 --- a/server/AyaNova/util/Seeder.cs +++ b/server/AyaNova/util/Seeder.cs @@ -2932,7 +2932,7 @@ namespace AyaNova.Util var woItemExpense = new WorkOrderItemExpense() { UserId = RandomServiceTechUserId(), - TotalCost = cost, + //TotalCost = cost, ChargeAmount = cost * 1.2m, ChargeToCustomer = true, ReimburseUser = true, @@ -2945,7 +2945,7 @@ namespace AyaNova.Util woItemExpense = new WorkOrderItemExpense() { UserId = RandomServiceTechUserId(), - TotalCost = cost * 2m, + // TotalCost = cost * 2m, ChargeAmount = cost * 2.2m, ChargeToCustomer = true, ReimburseUser = true,