How to set field value in a field marked as external?

Is there a way to accomplish this: I need to set field value in an field marked as external through BPM Data Directive? Context: Due to recent changes made by Mexican Tax Authority (SAT), all AR Invoices from customers marked as “Generic Public” must have a value (from SAT CFDI 4.0 catalog codes) in this fields: MXGlobalInvoiceMonth and MXGlobalInvoicePeriod.

When the ARInvoice is made through AR Invoice Entry program there is no problem due to the user can select this values in Header > Mexico > Detail, then when users post the AR Invoice this fiels are validated by a thidr party called PAC, and returns an XML signed digitallly.

The problem ocurs when the AR Invoice is created and posted by Counter Sales Proccess. According with a Tracing that I made, there is no Updated, UpdatedExt or UpdateMaster methods involved from Erp.BO.ARInvoice, just after click on Process Counter Sale button, therefore BPM Method Directives couldn’t be triggered.

Normally this problems could be soved using Set Field Widget whithin BPM Data Directive, but both of there is missing in ttInvcHead:

Looking at SQL database I saw that MXGlobalInvoiceMonth and MXGlobalInvoicePeriod currently are stored in [Ice].[PatchFld] table, Is ther a way to insert record in this table? i mean workaround?, because testing the BO.PatchFldImpl.UpdateExt method returns a “Creation of PatchFld not allowed”.

You could probably do direct db update, but you take your warranty in your hands when you do so.

Relevant Info for those interested:

From DB Schema Info:

Victor, tienes que tener una customization un poco mas compleja para anexo 24, hicimos algo similar hace tiempo si gustas te pongo en contacto con el developer para que te pase por ahi algo de direccion de momento yo no tengo esos detalles pero con gusto te contacto con el para que te pase algo de direccion.

@victorcarabez Just a theoretical workaround

If you added your own UD fields they would be in the schema so you could update them. Then you would have to set the validation fields to yours pre processing in the PAC validation process and then the returned XML would be valid.

I also found an MXInvcHeadFiscalText table, but without data I have no idea what this would hold.


Great post by Tim Shoemaker, I had already read it before, from there I discovered the location of the fields. I will try to solve the problem without making any SQL direct Insertions to the database. Thanks!

Making the change that you suggest would implicate modify this lines in this MXLoadComprobante.cs file, which is in charge of sending the invoice data to the PAC. But you helped me a lot since this process should not involve generating a global invoice, I think that these fields should not be sent to the PAC according to the Tax Authority (SAT) rules.

Thanks Greg!

1 Like

Es relacionado a Anexo 20, Factura No Global a Publico en General, pero generada desde la Orden de Venta (Counter Sales), creo que esos dos campos no deberian solicitarse para timbrar la factura, debe ser un problema de configuración.


Si puedes saber el número de factura creada en el Post Processing de ProcessCounterSale puedes intentar algo como lo siguiente (usado en el post processing de ARInvoiceSvc.GerShipments):

Ice.Diagnostics.Log.WriteEntry(string.Format(“Creating invoices {0}”, Invoices));
string[] invoices = Invoices.Split(‘~’);
using(var txscope = IceDataContext.CreateDefaultTransactionScope()){
foreach(string i in invoices){
Ice.Diagnostics.Log.WriteEntry(string.Format(“Processing invoice {0}”, i));
int iNum = Convert.ToInt32(i);
var inv = Db.InvcHead.FirstOrDefault(r=> r.Company == callContextClient.CurrentCompany && r.InvoiceNum == iNum);
if(inv != null){
var c = Db.Customer.FirstOrDefault(r=> r.Company == inv.Company && r.CustNum == inv.CustNum);
if(c != null && c.MXGeneralPublic){
PatchFld pfRow = new PatchFld();
pfRow.Company = callContextClient.CurrentCompany;
pfRow.TableName = “InvcHead”;
pfRow.ForeignKey = i;
pfRow.FieldName = “MXGlobalInvoicePeriod”;
pfRow.FieldDataType = “Character”;
pfRow.DataCharacter = “01”;

}catch(Exception e){
  Ice.Diagnostics.Log.WriteEntry(string.Format("Message: {0}; Stacktrace: {1}", e.Message, e.StackTrace));


Esta interesante el ejemplo que proporcionaste, lo voy a revisar, aunque si pudiera utilizar una BPM Post-Procesing utilizaria directamente el wigdet Set Field:

Muchas gracias.