@@ -648,23 +648,34 @@ export async function getReceiptDocTotal(aiSessionId: string): Promise<number |
648648export const CORRECTION_STREAK_GOAL = 30
649649
650650export interface CorrectionStreak {
651- correctedCount : number // de las últimas `totalCount` recepciones confirmadas
651+ correctedCount : number // de las últimas `totalCount` recepciones DEL ASISTENTE
652652 totalCount : number
653- streak : number // seguidas sin corrección, contando desde la más reciente
653+ streak : number // seguidas sin corrección, contando desde la más reciente (nunca > streakGoal)
654654 streakGoal : number
655655 metGoal : boolean // streak >= streakGoal
656656}
657657
658658/**
659- * Racha de recepciones confirmadas SIN que la oficina tuviera que corregir una
660- * cantidad (ENCARGO CODE 13/08 fix/recepcion-p2-oficina, §5). Recibe los ids de
661- * recepciones CONFIRMADAS ya cargados por el llamador (lista de Recepciones,
662- * ya filtrada por local), del más reciente al más antiguo — no vuelve a
663- * consultar goods_receipt, solo lee sus líneas. "Corregida" = alguna línea SIN
664- * ⚑ (flagged_for_office=false) con discrepancy_reason puesto por el picker de
665- * oficina (isOfficeQtyReason) — NO cualquier discrepancy_reason (el dropdown
666- * del panel de repaso usa el mismo campo para otra cosa: por qué difiere de lo
667- * pedido/del albarán).
659+ * Racha de recepciones DEL ASISTENTE (no el histórico entero) SIN que la
660+ * oficina tuviera que corregir una cantidad (ENCARGO CODE 13/08
661+ * fix/recepcion-p2-oficina, §5; recorte de alcance ENCARGO CODE 14/08
662+ * fix/recepcion-lista-recibido, §3). Recibe los candidatos ya cargados por el
663+ * llamador (recepciones 'recibido' o 'confirmado', ya filtradas por local),
664+ * del más reciente al más antiguo.
665+ *
666+ * "Del asistente" = status='recibido' (el flujo clásico nunca pasa por ahí),
667+ * o alguna línea con la ⚑ (flagged_for_office) — columna que solo escribe el
668+ * asistente, ninguna recepción del flujo clásico puede tenerla en true. No
669+ * hay columna que sobreviva la transición recibido→confirmado (añadirla es
670+ * migración, fuera de este encargo si hace falta) así que una recepción del
671+ * asistente con TODAS sus líneas sin marcar deja de detectarse en cuanto se
672+ * confirma — error hacia el lado seguro: cuenta de menos, nunca de más, así
673+ * que nunca dispara antes de tiempo la propuesta de confirmación directa.
674+ *
675+ * "Corregida" = alguna línea SIN ⚑ (flagged_for_office=false) con
676+ * discrepancy_reason puesto por el picker de oficina (isOfficeQtyReason) — NO
677+ * cualquier discrepancy_reason (el dropdown del panel de repaso usa el mismo
678+ * campo para otra cosa: por qué difiere de lo pedido/del albarán).
668679 *
669680 * ENCARGO CODE (13/08) feat/recepcion-v2-asistente, Tramo C — matiz del
670681 * asistente: una línea que cocina marcó ⚑ ("que lo mire la oficina") y que
@@ -673,33 +684,40 @@ export interface CorrectionStreak {
673684 * MARCAR (cocina dio por buena una cantidad que resultó ser otra).
674685 */
675686export async function getReceiptCorrectionStreak (
676- confirmedReceiptIdsRecentFirst : string [ ] ,
687+ candidatesRecentFirst : { id : string ; status : GoodsReceiptStatus } [ ] ,
677688) : Promise < CorrectionStreak > {
678689 requireSupabase ( )
679- if ( confirmedReceiptIdsRecentFirst . length === 0 ) {
690+ if ( candidatesRecentFirst . length === 0 ) {
680691 return { correctedCount : 0 , totalCount : 0 , streak : 0 , streakGoal : CORRECTION_STREAK_GOAL , metGoal : false }
681692 }
682693 const { data, error } = await from ( 'goods_receipt_line' )
683694 . select ( 'goods_receipt_id, discrepancy_reason, flagged_for_office' )
684- . in ( 'goods_receipt_id' , confirmedReceiptIdsRecentFirst )
695+ . in ( 'goods_receipt_id' , candidatesRecentFirst . map ( r => r . id ) )
685696 if ( error ) throw new Error ( `Error calculando la racha de correcciones: ${ error . message } ` )
697+ const lines = ( data as Row [ ] ) ?? [ ]
698+
699+ const flaggedIds = new Set ( lines . filter ( l => l . flagged_for_office ) . map ( l => l . goods_receipt_id as string ) )
700+ const assistantRecentFirst = candidatesRecentFirst
701+ . filter ( r => r . status === 'recibido' || flaggedIds . has ( r . id ) )
702+ . slice ( 0 , 60 )
686703
687704 const correctedIds = new Set < string > ( )
688- for ( const row of ( data as Row [ ] ) ?? [ ] ) {
705+ for ( const row of lines ) {
689706 if ( isOfficeQtyReason ( row . discrepancy_reason as string | null ) && ! row . flagged_for_office ) {
690707 correctedIds . add ( row . goods_receipt_id as string )
691708 }
692709 }
693710
694711 let streak = 0
695- for ( const id of confirmedReceiptIdsRecentFirst ) {
696- if ( correctedIds . has ( id ) ) break
712+ for ( const r of assistantRecentFirst ) {
713+ if ( correctedIds . has ( r . id ) ) break
697714 streak ++
715+ if ( streak >= CORRECTION_STREAK_GOAL ) break
698716 }
699717
700718 return {
701- correctedCount : correctedIds . size ,
702- totalCount : confirmedReceiptIdsRecentFirst . length ,
719+ correctedCount : assistantRecentFirst . filter ( r => correctedIds . has ( r . id ) ) . length ,
720+ totalCount : assistantRecentFirst . length ,
703721 streak,
704722 streakGoal : CORRECTION_STREAK_GOAL ,
705723 metGoal : streak >= CORRECTION_STREAK_GOAL ,
0 commit comments