Это делается в методе DoCreateSalesOrder(CreateSalesOrderFilter param)
, который вызывается в действии CreateSalesOrder
:
public PXAction<CROpportunity> createSalesOrder;
[PXUIField(DisplayName = Messages.CreateSalesOrder, MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Select)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntry)]
public virtual IEnumerable CreateSalesOrder(PXAdapter adapter)
{
foreach (CROpportunity opportunity in adapter.Get())
{
Customer customer = (Customer)PXSelect<Customer, Where<Customer.bAccountID, Equal<Current<CROpportunity.bAccountID>>>>
.SelectSingleBound(this, new object[] { opportunity });
if (customer == null)
{
throw new PXException(Messages.ProspectNotCustomer);
}
var products = Products.View.SelectMultiBound(new object[] { opportunity }).RowCast<CROpportunityProducts>();
if (products.Any(_ => _.InventoryID == null) && !products.Any(_ => _.InventoryID != null))
{
throw new PXException(Messages.SalesOrderHasOnlyNonInventoryLines);
}
if (CreateOrderParams.AskExtFullyValid((graph, viewName) => { }, DialogAnswerType.Positive))
{
Save.Press();
PXLongOperation.StartOperation(this, delegate()
{
var grapph = PXGraph.CreateInstance<OpportunityMaint>();
grapph.Opportunity.Current = opportunity;
grapph.CreateOrderParams.Current = CreateOrderParams.Current;
grapph.DoCreateSalesOrder(CreateOrderParams.Current);
});
}
yield return opportunity;
}
}
. Если мы посмотрим на этот метод, мы сможем найти следующие строки, создающие отношение:
var campaignRelation = docgraph.RelationsLink.Insert();
campaignRelation.RefNoteID = doc.NoteID;
campaignRelation.Role = CRRoleTypeList.Source;
campaignRelation.TargetType = CRTargetEntityType.CROpportunity;
campaignRelation.TargetNoteID = opportunity.NoteID;
campaignRelation.DocNoteID = opportunity.NoteID;
campaignRelation.EntityID = opportunity.BAccountID;
campaignRelation.ContactID = opportunity.ContactID;
docgraph.RelationsLink.Update(campaignRelation);
Полный код этого метода приведен ниже:
protected virtual void DoCreateSalesOrder(CreateSalesOrderFilter param)
{
bool recalcAny = param.RecalculatePrices == true ||
param.RecalculateDiscounts == true ||
param.OverrideManualDiscounts == true ||
param.OverrideManualDocGroupDiscounts == true ||
param.OverrideManualPrices == true;
var opportunity = this.Opportunity.Current;
Customer customer = (Customer)PXSelect<Customer, Where<Customer.bAccountID, Equal<Current<CROpportunity.bAccountID>>>>.Select(this);
SOOrderEntry docgraph = PXGraph.CreateInstance<SOOrderEntry>();
CurrencyInfo info = PXSelect<CurrencyInfo, Where<CurrencyInfo.curyInfoID, Equal<Current<CROpportunity.curyInfoID>>>>.Select(this);
info.CuryInfoID = null;
info = CurrencyInfo.GetEX(docgraph.currencyinfo.Insert(info.GetCM()));
SOOrder doc = new SOOrder();
doc.OrderType = CreateOrderParams.Current.OrderType ?? SOOrderTypeConstants.SalesOrder;
doc = docgraph.Document.Insert(doc);
doc = PXCache<SOOrder>.CreateCopy(docgraph.Document.Search<SOOrder.orderNbr>(doc.OrderNbr));
doc.CuryInfoID = info.CuryInfoID;
doc = PXCache<SOOrder>.CreateCopy(docgraph.Document.Update(doc));
doc.CuryID = info.CuryID;
doc.OrderDate = Accessinfo.BusinessDate;
doc.OrderDesc = opportunity.Subject;
doc.TermsID = customer.TermsID;
doc.CustomerID = opportunity.BAccountID;
doc.CustomerLocationID = opportunity.LocationID ?? customer.DefLocationID;
if (opportunity.TaxZoneID != null)
{
doc.TaxZoneID = opportunity.TaxZoneID;
if (!recalcAny)
{
SOTaxAttribute.SetTaxCalc<SOLine.taxCategoryID>(docgraph.Transactions.Cache, null, TaxCalc.ManualCalc);
SOTaxAttribute.SetTaxCalc<SOOrder.freightTaxCategoryID>(docgraph.Document.Cache, null,
TaxCalc.ManualCalc);
}
}
doc.ProjectID = opportunity.ProjectID;
doc.BranchID = opportunity.BranchID;
doc = docgraph.Document.Update(doc);
var campaignRelation = docgraph.RelationsLink.Insert();
campaignRelation.RefNoteID = doc.NoteID;
campaignRelation.Role = CRRoleTypeList.Source;
campaignRelation.TargetType = CRTargetEntityType.CROpportunity;
campaignRelation.TargetNoteID = opportunity.NoteID;
campaignRelation.DocNoteID = opportunity.NoteID;
campaignRelation.EntityID = opportunity.BAccountID;
campaignRelation.ContactID = opportunity.ContactID;
docgraph.RelationsLink.Update(campaignRelation);
bool failed = false;
foreach (CROpportunityProducts product in SelectProducts(opportunity.QuoteNoteID))
{
if (product.SiteID == null)
{
InventoryItem item = (InventoryItem)PXSelectorAttribute.Select<CROpportunityProducts.inventoryID>(Products.Cache, product);
if (item != null && item.NonStockShip == true)
{
Products.Cache.RaiseExceptionHandling<CROpportunityProducts.siteID>(product, null,
new PXSetPropertyException(ErrorMessages.FieldIsEmpty, typeof(CROpportunityProducts.siteID).Name));
failed = true;
}
}
SOLine tran = new SOLine();
tran = docgraph.Transactions.Insert(tran);
if (tran != null)
{
tran.InventoryID = product.InventoryID;
tran.SubItemID = product.SubItemID;
tran.TranDesc = product.Descr;
tran.OrderQty = product.Quantity;
tran.UOM = product.UOM;
tran.CuryUnitPrice = product.CuryUnitPrice;
tran.TaxCategoryID = product.TaxCategoryID;
tran.SiteID = product.SiteID;
tran.IsFree = product.IsFree;
tran.ProjectID = product.ProjectID;
tran.TaskID = product.TaskID;
tran.CostCodeID = product.CostCodeID;
tran.ManualPrice = true;
tran.ManualDisc = true;
tran.CuryDiscAmt = product.CuryDiscAmt;
tran.DiscAmt = product.DiscAmt;
tran.DiscPct = product.DiscPct;
tran.POCreate = product.POCreate;
tran.VendorID = product.VendorID;
if (param.RecalculatePrices != true)
{
tran.ManualPrice = true;
}
else
{
if (param.OverrideManualPrices != true)
tran.ManualPrice = product.ManualPrice;
else
tran.ManualPrice = false;
}
if (param.RecalculateDiscounts != true)
{
tran.ManualDisc = true;
}
else
{
if (param.OverrideManualDiscounts != true)
tran.ManualDisc = product.ManualDisc;
else
tran.ManualDisc = false;
}
tran.CuryDiscAmt = product.CuryDiscAmt;
tran.DiscAmt = product.DiscAmt;
tran.DiscPct = product.DiscPct;
}
tran = docgraph.Transactions.Update(tran);
PXNoteAttribute.CopyNoteAndFiles(Products.Cache, product, docgraph.Transactions.Cache, tran,
Setup.Current);
}
PXNoteAttribute.CopyNoteAndFiles(Opportunity.Cache, opportunity, docgraph.Document.Cache, doc, Setup.Current);
if (failed)
throw new PXException(Messages.SiteNotDefined);
//Skip all customer dicounts
if (param.RecalculateDiscounts != true && param.OverrideManualDiscounts != true)
{
var discounts = new Dictionary<string, SOOrderDiscountDetail>();
foreach (SOOrderDiscountDetail discountDetail in docgraph.DiscountDetails.Select())
{
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.skipDiscount>(discountDetail, true);
string key = discountDetail.Type + ':' + discountDetail.DiscountID + ':' + discountDetail.DiscountSequenceID;
discounts.Add(key, discountDetail);
}
Discount ext = this.GetExtension<Discount>();
foreach (CROpportunityDiscountDetail discountDetail in ext.DiscountDetails.Select())
{
SOOrderDiscountDetail detail;
string key = discountDetail.Type + ':' + discountDetail.DiscountID + ':' + discountDetail.DiscountSequenceID;
if (discounts.TryGetValue(key, out detail))
{
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.skipDiscount>(detail, false);
if (discountDetail.IsManual == true && discountDetail.Type == DiscountType.Document)
{
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.extDiscCode>(detail, discountDetail.ExtDiscCode);
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.description>(detail, discountDetail.Description);
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.isManual>(detail, discountDetail.IsManual);
docgraph.DiscountDetails.SetValueExt<SOOrderDiscountDetail.curyDiscountAmt>(detail, discountDetail.CuryDiscountAmt);
}
}
else
{
detail = (SOOrderDiscountDetail)docgraph.DiscountDetails.Cache.CreateInstance();
detail.Type = discountDetail.Type;
detail.DiscountID = discountDetail.DiscountID;
detail.DiscountSequenceID = discountDetail.DiscountSequenceID;
detail.ExtDiscCode = discountDetail.ExtDiscCode;
detail.Description = discountDetail.Description;
detail = (SOOrderDiscountDetail)docgraph.DiscountDetails.Cache.Insert(detail);
if (discountDetail.IsManual == true && (discountDetail.Type == DiscountType.Document || discountDetail.Type == DiscountType.ExternalDocument))
{
detail.CuryDiscountAmt = discountDetail.CuryDiscountAmt;
detail.IsManual = discountDetail.IsManual;
docgraph.DiscountDetails.Cache.Update(detail);
}
}
}
SOOrder old_row = PXCache<SOOrder>.CreateCopy(docgraph.Document.Current);
docgraph.Document.Cache.SetValueExt<SOOrder.curyDiscTot>(docgraph.Document.Current, DiscountEngineProvider.GetEngineFor<SOLine, SOOrderDiscountDetail>().GetTotalGroupAndDocumentDiscount(docgraph.DiscountDetails));
docgraph.Document.Cache.RaiseRowUpdated(docgraph.Document.Current, old_row);
}
doc = docgraph.Document.Update(doc);
if (opportunity.TaxZoneID != null && !recalcAny)
{
foreach (CRTaxTran tax in PXSelect<CRTaxTran, Where<CRTaxTran.quoteID, Equal<Current<CROpportunity.quoteNoteID>>>>.Select(this))
{
SOTaxTran newtax = new SOTaxTran();
newtax.LineNbr = int.MaxValue;
newtax.TaxID = tax.TaxID;
newtax = docgraph.Taxes.Insert(newtax);
if (newtax != null)
{
newtax = PXCache<SOTaxTran>.CreateCopy(newtax);
newtax.TaxRate = tax.TaxRate;
newtax.CuryTaxableAmt = tax.CuryTaxableAmt;
newtax.CuryTaxAmt = tax.CuryTaxAmt;
newtax.CuryUnshippedTaxableAmt = tax.CuryTaxableAmt;
newtax.CuryUnshippedTaxAmt = tax.CuryTaxAmt;
newtax.CuryUnbilledTaxableAmt = tax.CuryTaxableAmt;
newtax.CuryUnbilledTaxAmt = tax.CuryTaxAmt;
newtax = docgraph.Taxes.Update(newtax);
}
}
}
if (opportunity.AllowOverrideContactAddress == true)
{
CRContact _CRContact = Opportunity_Contact.SelectSingle();
CRAddress _CRAddress = Opportunity_Address.SelectSingle();
// Insert
if (_CRContact != null)
{
SOBillingContact _billingContact = docgraph.Billing_Contact.Select();
if (_billingContact != null)
{
_billingContact.FullName = _CRContact.FullName;
_billingContact.Salutation = _CRContact.Salutation;
_billingContact.Phone1 = _CRContact.Phone1;
_billingContact.Email = _CRContact.Email;
_billingContact = docgraph.Billing_Contact.Update(_billingContact);
_billingContact.IsDefaultContact = false;
_billingContact = docgraph.Billing_Contact.Update(_billingContact);
}
}
if (_CRAddress != null)
{
SOBillingAddress _billingAddress = docgraph.Billing_Address.Select();
if (_billingAddress != null)
{
_billingAddress.AddressLine1 = _CRAddress.AddressLine1;
_billingAddress.AddressLine2 = _CRAddress.AddressLine2;
_billingAddress.City = _CRAddress.City;
_billingAddress.CountryID = _CRAddress.CountryID;
_billingAddress.State = _CRAddress.State;
_billingAddress.PostalCode = _CRAddress.PostalCode;
_billingAddress = docgraph.Billing_Address.Update(_billingAddress);
_billingAddress.IsDefaultAddress = false;
_billingAddress = docgraph.Billing_Address.Update(_billingAddress);
}
}
}
if (recalcAny)
{
docgraph.recalcdiscountsfilter.Current.OverrideManualPrices = param.OverrideManualPrices == true;
docgraph.recalcdiscountsfilter.Current.RecalcDiscounts = param.RecalculateDiscounts == true;
docgraph.recalcdiscountsfilter.Current.RecalcUnitPrices = param.RecalculatePrices == true;
docgraph.recalcdiscountsfilter.Current.OverrideManualDiscounts = param.OverrideManualDiscounts == true;
docgraph.recalcdiscountsfilter.Current.OverrideManualDocGroupDiscounts = param.OverrideManualDocGroupDiscounts == true;
docgraph.Actions[nameof(Discount.RecalculateDiscountsAction)].Press();
}
if (!this.IsContractBasedAPI)
throw new PXRedirectRequiredException(docgraph, "");
docgraph.Save.Press();
}
ПРИМЕЧАНИЕ: большую часть источников можно найти по следующему пути вПапка сервера Acumatica App_Data\CodeRepository\PX.Objects
, App_Data\CodeRepository\PX.Data
, App_Data\CodeRepository\PX.Objects.FS