Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

 Este documento é material de especificação dos requisitos de inovação, trata-se de conteúdo extremamente técnico.



Informações Gerais

 

Especificação

Produto

Microsiga Protheus

Módulo

SIGAWMS - Gestão de Armazenagem

Segmento Executor

Distribuição &

Supply Chain - Logística

Projeto

M_DL_WMS002

IRM

PCREQ-9339

Requisito

PCREQ-9340

Subtarefa

PDRDL-2452

Release de Entrega Planejada

11.80.16


Réplica

 


País

(

x

X ) Brasil  (  ) Argentina  (  ) México  (  ) Chile  (  ) Paraguai  (  ) Equador

(  ) USA  (  ) Colômbia   (  ) Outro _____________.

Outros

 


Objetivo

Permitir a junção (aglutinação) de quantidades iguais de um mesmo produto dentro de uma mesma carga ou, prevendo alterações futuras, de um mesmo plano de movimentação a fim de otimizar as movimentações no armazém priorizando a expedição de endereços de tipo pulmão quando a junção dos pedidos que compõe a carga ou plano solicitarem uma quantidade maior que uma norma do produto.

Esta alteração, diferente da aglutinação dos movimentos das atividades, configurada pelo cadastro de tarefa x atividade, aglutina as quantidade das ordens de serviço que geram um movimento de uma norma, priorizando a retirado do pulmão de forma mais eficiente.

Adequar o processo de aglutinação para permitir as movimentações por onda (plano de movimentação), que possibilitará a aglutinação de serviços de entrada e saída independente da carga ou cliente, será criado na ordem de serviço a indicação de qual plano a ordem de serviço pertence e assim juntar as quantidades dos produtos. 


Definição da Regra de Negócio

A execução das ordens de serviço pelo WMSA150 realiza uma busca das DCF selecionadas e uma por uma posiciona no registro e chama o método ExecuteDCF, a ideia é logo após o posicionamento utilizar das características do registro para buscar as ordens que podem ser aglutinadas. Encontrado os dados, será somado a variável da quantidade do DCF posicionado no objeto com as quantidades de todas as ordens de serviço do array, mas será precisa alterar também o status de cada DCF, para que não seja executada em seguida, e a criação da DCR para respeitar o array de ordens aglutinadas encontradas, o que mantém o relacionamento com a ordem de serviço original. 

Primeiramente, é de conhecimento que a alteração é aplicável somente para o novo WMS, ou seja, o parâmetro MV_WMSNEW precisa estar igual a .T., assim como o ambiente de desenvolvimento.

Conter no dicionário o parâmetro MV_WMSACEX que pode ser criado aplicando o update WMSU0033, acessado via WMSUMAIN.

A alteração inicia-se com a criação de dois atributos da classe WMSDTCOrdemServico:

  • cCodPln > Código do plano de movimentação
  • aOrdAglu > Array de ordens de serviço aglutinadas

*Lembrando que a criação de cada atributo precisa vir com os métodos Getters e Setters correspondentes.

Como o atributo cCodPln da classe corresponde ao campo DCF_CODPLN que será criado, ele precisa ser considerado nos métodos LoadData (utilizar FieldPos ao atribuir o valor) , RecordDCF e UpdateDCF (utilizar o método Getter e Setter criado).

 

Dentro do método ExecuteDCF da classe WMSDTCOrdemServicoExecute logo após a validação se o 'Self:cIdDCF' está preenchidoapós as validações e antes de iniciar o bloco transaction, criar a chamada de um método que realizará a busca das ordens de serviço semelhantes e adicionará ao array aOrdAglu. Este método precisa ser criado na WMSDTCOrdemServico para futuras aplicações.

O select de busca precisa prever a informação do campo DCF_CODPLN e para o filtro deve ser utilizado os atributos da classe.

O filtro precisa respeitar serviço, armazém, produto, lote, sub-lote, endereço, status diferente de '3=Executado' e quando o atributo cCodPln estiver preenchido, o plano, quando estiver vazio,considerar e a função WMSCargafunção WMSCarga() e a carga ao invés do plano. Quando MV_WMSACEX for '2', considerar no filtro o cliente e loja somente quando o plano estiver vazio.

Prevendo alterações futuras referente ao plano de movimentação, o endereço que precisa ser considerado no select no select varia dependendo do serviço que está sendo executado. Quando for um serviço de separação (Self:oServico:ChkSepara()), considerar armazém e endereço origem, pelo contrário, armazém e endereço destino, conforme exemplo:

" SELECT DCF.DCF_ID, DCF.DCF_NUMSEQ, DCF.DCF_QUANT, DCF.R_E_C_N_O_ RECNODCF"
" FROM "+RetSqlName("DCF")+" DCF"
" WHERE DCF.DCF_FILIAL = '"+xFilial("DCF")+"'"
" AND DCF.DCF_SERVIC = '"+Self:oServico:GetServico()+"'"
" AND DCF.DCF_CODPRO = '"+Self:oProdLote:GetProduto()+"'"
If !Empty(Self:GetPlnExp())
" AND DCF.DCF_PLNEXP = '"+Self:GetPlnExp()+"'"
ElseIf WmsCarga(Self:GetCarga())
If SuperGetMv("MV_WMSACEX",.F.,"0") == '2' // Se aglutina por cliente
" AND DCF.DCF_CLIFOR = '"+Self:GetCliFor()+"'"
" AND DCF.DCF_LOJA = '"+Self:GetLoja()+"'"
EndIf
" AND DCF.DCF_CARGA = '"+Self:GetCarga()+"'"
EndIf
If Self:oServico:ChkSepara()
" AND DCF.DCF_LOCAL = '"+Self:oOrdEndOri:GetArmazem()+"'"
" AND DCF.DCF_ENDER = '"+Self:oOrdEndOri:GetEnder()+"'"
Else
" AND DCF.DCF_LOCDES = '"+Self:oOrdEndDes:GetArmazem()+"'"
" AND DCF.DCF_ENDDES = '"+Self:oOrdEndDes:GetEnder()+"'"
EndIf
" AND DCF.DCF_LOTECT = '"+Self:oProdLote:GetLoteCtl()+"'"
" AND DCF.DCF_NUMLOT = '"+Self:oProdLote:GetNumLote()+"'"
" AND DCF.DCF_STSERV <> '3'"
" AND DCF.R_E_C_N_O_ <> "+Self:GetRecno()
" AND DCF.D_E_L_E_T_ = ' '"

*Importante manter esta ordem no filtro do select para que o banco de dados utilize do índice mais apropriado.

Retornar os campos DCF_ID, DCF_NUMSEQ, DCF_QUANT, DCF_DOCTO, DCF_SERIE, DCF_CLIFOR, DCF_LOJA, DCF_SEQUEN, R_E_C_N_O_ e , adicionar cada linha no arrayaOrdAglu. aOrdAglu e criar na ultima posição um vetor vazio que posteriormente será carregado com as atividades do serviço e suas quantidades.

Este array Este array sempre precisará conter pelo menos um registro, que será o DCF atual. Para isso, preencher a primeira posição os valores do objeto da DCF atual e depois com depois com o que encontrar no select. No inicio do método, certificar que array o array inicialize como vazio.

Inicializar uma variável nQtdOrdSer, que conterá a quantidade sumarizada da aglutinação, com o Self:nQuant do objeto atual e incrementar na mesma variável para cada DCF_QUANT retornado do select de ordens de serviço possíveis de aglutinação. Após isso, substituir o valor do Self:nQuant por nQtdOrdSer.

Ordenar array o array por IDDCF com a função aSort para aSort para garantir a ordem na execução assim como as quantidades na hora da criação dos movimentos em passos posteriores.

 

Voltando para o No método ExecuteDCF da classe WMSDTCOrdemServicoExecute, alterar o bloco que atualiza o status da DCF posicionada no objeto para repetir para cada recno do aOrdAglu. Criar um laço de repetição pelo tamanho do array aOrdAglu.

O bloco que precisa repetir para atualizar o status é:

// Atualiza status

Self:SetStServ('3')

Self:SetOk("")

Self:UpdateDCF()

Self:UpdStatus()

Porém será preciso reposicionar o objeto para atualizar cada DCF. Utilizar o método GoToDCF(nRecno) quando Len(aOrdAglu) > 1, passando o recno de cada DCF do array por parâmetro. Ao terminar o laço de atualização do status, é preciso voltar a DCF posicionada original para que o Self:UnLockDCF() realize sua função corretamente, assim como o restante do processo.

No método ExecutePrd, antes do comando 'For' de aProdutos, definir os campos na ultima posição do array aOrdAglu. Percorrer o tamanho de aOrdAglu e adicionar mais espaço para quando o produto for partes e então adicionar a quantidade multiplicada pelo múltiplo do componente neste sub-array de aOrdAglu.

Antes de chamar a execução da função (oFuncao:ExecFuncao) atribuir o array aOrdAglu ao objeto do movimento, como deixamos o registro atual como ultima posição do array, não será preciso voltar o DCFassim como aRecD12 e aLibD12

Em WMSDTCMovimentosServicoArmazem método AssignD12 antes do comando 'For' de  aAtividade, realizar o rateio para a tarefa da quantidade total solicitada dentre os ID DCF que estão no array, isso determinará quanto cada ID DCF será atendido pela quantidade total do movimento, conforme exemplo:

nQtSol := Self:nQtdMovto

nOrdPrd := Self:oOrdServ:nProduto

nOrdTar := Self:oOrdServ:nTarefa

For nI := 1 To Len(Self:aOrdAglu)

aAgluMov := Self:aOrdAglu[nI][POSTAREFA][nOrdPrd][nOrdTar]

If (aAgluMov[POSQTDSOL] - aAgluMov[POSQTDATD]) > 0

aAgluMov[POSIDDCF] := Self:oOrdServ:GetIdDCF()

If nQtSol > (aAgluMov[POSQTDSOL] - aAgluMov[POSQTDATD])

nQtSol -= (aAgluMov[POSQTDSOL] - aAgluMov[POSQTDATD])

aAgluMov[POSQTDMOV] := (aAgluMov[POSQTDSOL] - aAgluMov[POSQTDATD]) //Utiliza todo o saldo

Else

aAgluMov[POSQTDMOV] := nQtSol

nQtSol := 0

EndIf

// Grava o total atendido

aAgluMov[POSQTDATD] += aAgluMov[POSQTDMOV]

If nQtSol == 0

Exit

EndIf

EndIf

Next nI

Ao final da execução das atividades será preciso zerar as quantidades distribuídas da movimentação, ou seja, zerar a posição com a quantidade da movimentação de todos os sub-arrays de aOrdAglu.

Assim como a atualização do status para cada ordem de serviço, é preciso criar os registros DCR das ordens aglutinadas. Na classe WMSDTCMovimentosServicoArmazem método RecordD12, alterar o bloco "Grava relacionamento movimento serviço armazém" para cada ordem de serviço do array , substituindo...

oRelacMov:SetIdDCF

conforme exemplo:

// Grava relacionamento movimento servico armazem

nOrdPrd := Self:oOrdServ:nProduto

nOrdTar := Self:oOrdServ:nTarefa

For nI := 1 To Len(Self:aOrdAglu)

aAgluMov := Self:aOrdAglu[nI][POSTAREFA][nOrdPrd][nOrdTar]

If aAgluMov[POSQTDMOV] > 0

cIdDCF := aAgluMov[POSIDDCF]

nQtdMovto := aAgluMov[POSQTDMOV]

nQtdMovto2 := ConvUm(Self:oMovPrdLot:GetProduto(),nQtdMovto,0,2)

oRelacMov:SetIdOrig(cIdDCF)

oRelacMov:

SetSequen(cSequen)

SetIdDCF(Self:aOrdAglu[nI][1])

oRelacMov:SetIdMovto(IIF(lAglutina,D12->D12_IDMOV,cIdMovto))

oRelacMov:SetIdOpera(IIF(lAglutina,D12->D12_IDOPER,cIdOpera))

oRelacMov:SetSequen(cSequen)

If oRelacMov:LoadData()

oRelacMov:SetQuant(oRelacMov:GetQuant()+nQtdMovto)

oRelacMov:SetQuant2(oRelacMov:GetQuant2()+nQtdMovto2)

oRelacMov:UpdateDCR()

Else

oRelacMov:SetQuant(nQtdMovto)

oRelacMov:SetQuant2(nQtdMovto2)

oRelacMov:RecordDCR()

EndIf

nQtdTotal += nQtdMovto

EndIf

Next nI

nQtdMovto := nQtdTotal

nQtdMovto2 := ConvUm(Self:oMovPrdLot:GetProduto(),nQtdMovto,0,2)

pelos valores do array aOrdAglu.

- Os registros DCR desse movimento precisam ter o mesmo DCR_IDORI, que seria o iddcf do próprio objeto, não precisando ser alterado;

- DCR_IDMOV, DCR_IDOPER e DCR_QUANT com o mesmo valor do método;

- DCF_IDDCF e DCR_SEQUEN correspondente a cada registro do array.

Igualmente a atualização do status, este laço de repetição sempre acontecerá a partir desta alteração, pois o array conterá pelo menos uma DCF.

 

Finalmente, será preciso alterar o processo de conferência de saída para considerar array o array de ordens de serviço aglutinadas. A conferência de saída (DLConfSai()) não deve gerar movimentos aglutinados, por isso é preciso considerar todos os identificados da DCF para que cada movimento seja criado com a quantidade correta. Em WMSBCCConferenciaSaida método ProcConfSai alterar select o select das movimentações buscando por todos os identificadores da DCF do array do array ao invés do posicionado, conforme exemplo:

" AND DCR.DCR_IDDCF IN ('000001','000002','000003','000004') " 

Criar no update do projeto (WMSNEWUPD) o campo com as informações abaixo em Dicionário de Dados. 

Rotina

Tipo de Operação

Opção de Menu

Regras de Negócio

WMSDTCOrdemServico

Alteração

 

 



WMSDTCOrdemServicoExecute

Alteração

 

 



WMSDTCMovimentosServicoArmazem

Alteração

 

 

WMSUXXXXCriaçãoExecutado via WMSUMAIN 

 



WMSNEWUPDAlteração

Exemplo de Aplicação

  • Configurar

    o

    parâmetro

    MV_WMSACEX

    com

    o

    valor

    '1=Aglutina

    por

    Carga'

    ou

    '2=Aglutina

    por

    Carga/Cliente'.

  • Criar

    vários

    pedidos

    de

    venda

    que

    realizam

    montagem

    de

    carga

    e

    que

    geram

    o

    serviço

    WMS

    na

    montagem

    de

    carga,

    com

    os

    mesmos

    produtos

    entre

    eles.

  • Criar

    uma

    ou

    mais

    cargas

    com

    os

    pedidos

    criados.

  • Ao

    executar

    os

    serviços,

    os

    movimentos

    da

    D12

    devem

    juntar

    a

    quantidade

    dos

    produtos

    iguais

    em

    um

    único

    movimento

    respeitando

    a

    norma.

  • Verificar

    se

    os

    dados

    da

    DCR

    consistem.

  • Estornar

    e

    executar

    várias

    vezes

    para

    garantir

    que o estorno não deixe lixo na base

    o saldo do produto.

Tabelas Utilizadas

  • DCF – Ordem de Serviço

  • D12 – Movimentos Serviço WMS

  • DCR – Relacionamento Movimentos Distribuição


Dicionário de Dados

Arquivo : DCF – Ordem de Serviço  

Campo

DCF_CODPLN

Tipo

C

Tamanho

6

Valor Inicial

 


Mandatório

Sim (  ) Não (x)

Descrição

Código do plano de movimentação.

Título

Cód. Plano

Picture

@!

Help de Campo

Utilizado para indicar as ordens de serviço que terão seus produtos aglutinados.

 


 Este documento é material de especificação dos requisitos de inovação, trata-se de conteúdo extremamente técnico.