797 lines
24 KiB
TypeScript
797 lines
24 KiB
TypeScript
import { Component, Inject, PLATFORM_ID, OnInit, OnDestroy } from '@angular/core';
|
|
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { HttpClient } from '@angular/common/http';
|
|
import { ChipsControleService, ChipVirgemListDto, ControleRecebidoListDto, SortDir, UpdateChipVirgemRequest, UpdateControleRecebidoRequest, CreateChipVirgemRequest, CreateControleRecebidoRequest } from '../../services/chips-controle.service';
|
|
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
|
|
import { AuthService } from '../../services/auth.service';
|
|
|
|
// Interface para o Agrupamento
|
|
interface ChipGroup {
|
|
observacao: string;
|
|
total: number;
|
|
items: ChipVirgemListDto[];
|
|
}
|
|
|
|
interface ControleGroup {
|
|
conteudo: string;
|
|
total: number;
|
|
items: ControleRecebidoListDto[];
|
|
}
|
|
|
|
interface ChipVirgemCreateModel {
|
|
id: string;
|
|
item: number | null;
|
|
numeroDoChip: string | null;
|
|
observacoes: string | null;
|
|
}
|
|
|
|
type ChipsSortKey = 'item' | 'numeroDoChip' | 'observacoes';
|
|
type ControleSortKey =
|
|
| 'ano' | 'item' | 'notaFiscal' | 'chip' | 'serial' | 'conteudoDaNf' | 'numeroDaLinha'
|
|
| 'valorUnit' | 'valorDaNf' | 'dataDaNf' | 'dataDoRecebimento' | 'quantidade' | 'isResumo';
|
|
|
|
@Component({
|
|
selector: 'app-chips-controle-recebidos',
|
|
standalone: true,
|
|
imports: [CommonModule, FormsModule, CustomSelectComponent],
|
|
templateUrl: './chips-controle-recebidos.html',
|
|
styleUrls: ['./chips-controle-recebidos.scss']
|
|
})
|
|
export class ChipsControleRecebidos implements OnInit, OnDestroy {
|
|
activeTab: 'chips' | 'controle' = 'chips';
|
|
|
|
// --- Chips ---
|
|
chipsRows: ChipVirgemListDto[] = [];
|
|
chipsGroups: ChipGroup[] = [];
|
|
pagedChipsGroups: ChipGroup[] = [];
|
|
expandedGroupObservacao: string | null = null;
|
|
|
|
chipsLoading = false;
|
|
chipsSearch = '';
|
|
chipsPage = 1;
|
|
chipsPageSize = 10;
|
|
chipsTotal = 0;
|
|
chipsSortBy: ChipsSortKey = 'item';
|
|
chipsSortDir: SortDir = 'asc';
|
|
private chipsSearchTimer: any = null;
|
|
|
|
// --- Controle ---
|
|
controleRows: ControleRecebidoListDto[] = [];
|
|
controleGroups: ControleGroup[] = [];
|
|
pagedControleGroups: ControleGroup[] = [];
|
|
expandedControleConteudo: string | null = null;
|
|
controleLoading = false;
|
|
controleSearch = '';
|
|
controlePage = 1;
|
|
controlePageSize = 10;
|
|
controleTotal = 0;
|
|
controleSortBy: ControleSortKey = 'ano';
|
|
controleSortDir: SortDir = 'desc';
|
|
controleAno: number | '' = '';
|
|
controleResumo: '' | 'true' | 'false' = '';
|
|
private controleSearchTimer: any = null;
|
|
|
|
// --- Opções ---
|
|
pageSizeOptions = [10, 20, 50, 100];
|
|
anoOptions = [
|
|
{ label: 'Todos', value: '' },
|
|
{ label: '2022', value: 2022 },
|
|
{ label: '2023', value: 2023 },
|
|
{ label: '2024', value: 2024 },
|
|
{ label: '2025', value: 2025 }
|
|
];
|
|
|
|
toastOpen = false;
|
|
toastMessage = '';
|
|
toastType: 'success' | 'danger' = 'success';
|
|
private toastTimer: any = null;
|
|
|
|
chipDetailOpen = false;
|
|
chipDetailLoading = false;
|
|
chipDetailData: ChipVirgemListDto | null = null;
|
|
chipCreateOpen = false;
|
|
chipCreateSaving = false;
|
|
chipCreateModel: ChipVirgemCreateModel | null = null;
|
|
chipEditOpen = false;
|
|
chipEditSaving = false;
|
|
chipEditModel: ChipVirgemListDto | null = null;
|
|
chipEditingId: string | null = null;
|
|
chipDeleteOpen = false;
|
|
chipDeleteTarget: ChipVirgemListDto | null = null;
|
|
|
|
controleDetailOpen = false;
|
|
controleDetailLoading = false;
|
|
controleDetailData: ControleRecebidoListDto | null = null;
|
|
controleCreateOpen = false;
|
|
controleCreateSaving = false;
|
|
controleCreateModel: ControleRecebidoListDto | null = null;
|
|
controleCreateDataNf = '';
|
|
controleCreateRecebimento = '';
|
|
controleEditOpen = false;
|
|
controleEditSaving = false;
|
|
controleEditModel: ControleRecebidoListDto | null = null;
|
|
controleEditDataNf = '';
|
|
controleEditRecebimento = '';
|
|
controleEditingId: string | null = null;
|
|
controleDeleteOpen = false;
|
|
controleDeleteTarget: ControleRecebidoListDto | null = null;
|
|
|
|
isAdmin = false;
|
|
|
|
constructor(
|
|
@Inject(PLATFORM_ID) private platformId: object,
|
|
private service: ChipsControleService,
|
|
private http: HttpClient,
|
|
private authService: AuthService
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
if (!isPlatformBrowser(this.platformId)) return;
|
|
this.isAdmin = this.authService.hasRole('admin');
|
|
this.fetchChips();
|
|
this.fetchControle();
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
if (this.chipsSearchTimer) clearTimeout(this.chipsSearchTimer);
|
|
if (this.controleSearchTimer) clearTimeout(this.controleSearchTimer);
|
|
if (this.toastTimer) clearTimeout(this.toastTimer);
|
|
}
|
|
|
|
setTab(tab: 'chips' | 'controle') {
|
|
this.activeTab = tab;
|
|
|
|
if (tab === 'chips') {
|
|
this.expandedGroupObservacao = null;
|
|
this.applyChipsPagination();
|
|
this.closeControleDetail();
|
|
} else {
|
|
this.expandedControleConteudo = null;
|
|
this.applyControlePagination();
|
|
this.closeChipDetail();
|
|
}
|
|
}
|
|
|
|
// =====================
|
|
// Chips Virgens
|
|
// =====================
|
|
fetchChips() {
|
|
this.chipsLoading = true;
|
|
|
|
this.service.getChipsVirgens({
|
|
search: this.chipsSearch,
|
|
page: 1,
|
|
pageSize: 5000,
|
|
sortBy: this.chipsSortBy,
|
|
sortDir: this.chipsSortDir
|
|
}).subscribe({
|
|
next: (res) => {
|
|
const items = (res as any)?.items ?? [];
|
|
this.chipsRows = items.map((x: any, idx: number) => this.normalizeChip(x, idx));
|
|
this.buildChipsGroups();
|
|
this.chipsTotal = this.chipsGroups.length;
|
|
this.applyChipsPagination();
|
|
this.chipsLoading = false;
|
|
},
|
|
error: () => {
|
|
this.chipsLoading = false;
|
|
this.showToast('Erro ao carregar Chips Virgens.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
private buildChipsGroups() {
|
|
const groupsMap = new Map<string, ChipVirgemListDto[]>();
|
|
|
|
this.chipsRows.forEach(row => {
|
|
const key = row.observacoes && row.observacoes.trim() !== ''
|
|
? row.observacoes.trim()
|
|
: '(Sem Observações)';
|
|
|
|
if (!groupsMap.has(key)) groupsMap.set(key, []);
|
|
groupsMap.get(key)?.push(row);
|
|
});
|
|
|
|
this.chipsGroups = [];
|
|
groupsMap.forEach((items, key) => {
|
|
this.chipsGroups.push({ observacao: key, total: items.length, items });
|
|
});
|
|
|
|
this.chipsGroups.sort((a, b) => a.observacao.localeCompare(b.observacao));
|
|
this.expandedGroupObservacao = null;
|
|
}
|
|
|
|
private applyChipsPagination() {
|
|
const start = (this.chipsPage - 1) * this.chipsPageSize;
|
|
const end = start + this.chipsPageSize;
|
|
this.pagedChipsGroups = this.chipsGroups.slice(start, end);
|
|
|
|
if (this.expandedGroupObservacao && !this.pagedChipsGroups.some(g => g.observacao === this.expandedGroupObservacao)) {
|
|
this.expandedGroupObservacao = null;
|
|
}
|
|
}
|
|
|
|
toggleGroup(obs: string) {
|
|
this.expandedGroupObservacao = this.expandedGroupObservacao === obs ? null : obs;
|
|
}
|
|
|
|
openChipDetail(row: ChipVirgemListDto) {
|
|
if (!row?.id) return;
|
|
this.chipDetailOpen = true;
|
|
this.chipDetailLoading = true;
|
|
this.chipDetailData = null;
|
|
|
|
this.service.getChipVirgemById(row.id).subscribe({
|
|
next: (data) => {
|
|
this.chipDetailData = data ?? row;
|
|
this.chipDetailLoading = false;
|
|
},
|
|
error: () => {
|
|
this.chipDetailLoading = false;
|
|
this.chipDetailData = row;
|
|
}
|
|
});
|
|
}
|
|
|
|
openChipCreate() {
|
|
if (!this.isAdmin) return;
|
|
this.chipCreateModel = {
|
|
id: '',
|
|
item: null,
|
|
numeroDoChip: '',
|
|
observacoes: ''
|
|
};
|
|
this.chipCreateOpen = true;
|
|
this.chipCreateSaving = false;
|
|
}
|
|
|
|
closeChipCreate() {
|
|
this.chipCreateOpen = false;
|
|
this.chipCreateSaving = false;
|
|
this.chipCreateModel = null;
|
|
}
|
|
|
|
saveChipCreate() {
|
|
if (!this.chipCreateModel) return;
|
|
this.chipCreateSaving = true;
|
|
|
|
const payload: CreateChipVirgemRequest = {
|
|
item: this.toNullableNumber(this.chipCreateModel.item),
|
|
numeroDoChip: this.chipCreateModel.numeroDoChip,
|
|
observacoes: this.chipCreateModel.observacoes
|
|
};
|
|
|
|
this.service.createChipVirgem(payload).subscribe({
|
|
next: () => {
|
|
this.chipCreateSaving = false;
|
|
this.closeChipCreate();
|
|
this.fetchChips();
|
|
this.showToast('Chip criado com sucesso!', 'success');
|
|
},
|
|
error: () => {
|
|
this.chipCreateSaving = false;
|
|
this.showToast('Erro ao criar chip.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
openChipEdit(row: ChipVirgemListDto) {
|
|
if (!this.isAdmin) return;
|
|
this.service.getChipVirgemById(row.id).subscribe({
|
|
next: (data) => {
|
|
this.chipEditingId = data.id;
|
|
this.chipEditModel = { ...data };
|
|
this.chipEditOpen = true;
|
|
},
|
|
error: () => this.showToast('Erro ao abrir edição.', 'danger')
|
|
});
|
|
}
|
|
|
|
closeChipEdit() {
|
|
this.chipEditOpen = false;
|
|
this.chipEditSaving = false;
|
|
this.chipEditModel = null;
|
|
this.chipEditingId = null;
|
|
}
|
|
|
|
saveChipEdit() {
|
|
if (!this.chipEditModel || !this.chipEditingId) return;
|
|
this.chipEditSaving = true;
|
|
const payload: UpdateChipVirgemRequest = {
|
|
item: this.toNullableNumber(this.chipEditModel.item),
|
|
numeroDoChip: this.chipEditModel.numeroDoChip,
|
|
observacoes: this.chipEditModel.observacoes
|
|
};
|
|
this.service.updateChipVirgem(this.chipEditingId, payload).subscribe({
|
|
next: () => {
|
|
this.chipEditSaving = false;
|
|
this.closeChipEdit();
|
|
this.fetchChips();
|
|
this.showToast('Chip atualizado!', 'success');
|
|
},
|
|
error: () => {
|
|
this.chipEditSaving = false;
|
|
this.showToast('Erro ao salvar.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
openChipDelete(row: ChipVirgemListDto) {
|
|
if (!this.isAdmin) return;
|
|
this.chipDeleteTarget = row;
|
|
this.chipDeleteOpen = true;
|
|
}
|
|
|
|
cancelChipDelete() {
|
|
this.chipDeleteOpen = false;
|
|
this.chipDeleteTarget = null;
|
|
}
|
|
|
|
confirmChipDelete() {
|
|
if (!this.chipDeleteTarget) return;
|
|
const id = this.chipDeleteTarget.id;
|
|
this.service.removeChipVirgem(id).subscribe({
|
|
next: () => {
|
|
this.chipDeleteOpen = false;
|
|
this.chipDeleteTarget = null;
|
|
this.fetchChips();
|
|
this.showToast('Chip removido.', 'success');
|
|
},
|
|
error: () => {
|
|
this.chipDeleteOpen = false;
|
|
this.chipDeleteTarget = null;
|
|
this.showToast('Erro ao remover.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
closeChipDetail() {
|
|
this.chipDetailOpen = false;
|
|
this.chipDetailLoading = false;
|
|
this.chipDetailData = null;
|
|
}
|
|
|
|
onChipsSearch() {
|
|
if (this.chipsSearchTimer) clearTimeout(this.chipsSearchTimer);
|
|
this.chipsSearchTimer = setTimeout(() => {
|
|
this.chipsPage = 1;
|
|
this.fetchChips();
|
|
}, 300);
|
|
}
|
|
|
|
clearChipsSearch() {
|
|
this.chipsSearch = '';
|
|
this.chipsPage = 1;
|
|
this.fetchChips();
|
|
}
|
|
|
|
onChipsPageSizeChange() {
|
|
this.chipsPage = 1;
|
|
this.applyChipsPagination();
|
|
}
|
|
|
|
// =====================
|
|
// Controle Recebidos
|
|
// =====================
|
|
fetchControle() {
|
|
this.controleLoading = true;
|
|
|
|
this.service.getControleRecebidos({
|
|
search: this.controleSearch,
|
|
page: 1,
|
|
pageSize: 5000,
|
|
sortBy: this.controleSortBy,
|
|
sortDir: this.controleSortDir,
|
|
ano: this.controleAno,
|
|
isResumo: this.controleResumo
|
|
}).subscribe({
|
|
next: (res) => {
|
|
const items = (res as any)?.items ?? [];
|
|
this.controleRows = items.map((x: any, idx: number) => this.normalizeControle(x, idx));
|
|
this.buildControleGroups();
|
|
this.controleTotal = this.controleGroups.length;
|
|
this.applyControlePagination();
|
|
this.controleLoading = false;
|
|
},
|
|
error: () => {
|
|
this.controleLoading = false;
|
|
this.showToast('Erro ao carregar Controle.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
onControleSearch() {
|
|
if (this.controleSearchTimer) clearTimeout(this.controleSearchTimer);
|
|
this.controleSearchTimer = setTimeout(() => {
|
|
this.controlePage = 1;
|
|
this.fetchControle();
|
|
}, 300);
|
|
}
|
|
|
|
clearControleSearch() {
|
|
this.controleSearch = '';
|
|
this.controlePage = 1;
|
|
this.fetchControle();
|
|
}
|
|
|
|
setControleSort(key: ControleSortKey) {
|
|
if (this.controleSortBy === key) {
|
|
this.controleSortDir = this.controleSortDir === 'asc' ? 'desc' : 'asc';
|
|
} else {
|
|
this.controleSortBy = key;
|
|
this.controleSortDir = 'asc';
|
|
}
|
|
this.controlePage = 1;
|
|
this.fetchControle();
|
|
}
|
|
|
|
onControlePageSizeChange() {
|
|
this.controlePage = 1;
|
|
this.applyControlePagination();
|
|
}
|
|
|
|
onControleAnoChange() {
|
|
this.controlePage = 1;
|
|
this.fetchControle();
|
|
}
|
|
|
|
setControleResumo(val: '' | 'true' | 'false') {
|
|
this.controleResumo = val;
|
|
this.controlePage = 1;
|
|
this.fetchControle();
|
|
}
|
|
|
|
private buildControleGroups() {
|
|
const groupsMap = new Map<string, ControleRecebidoListDto[]>();
|
|
|
|
this.controleRows.forEach(row => {
|
|
const key = row.conteudoDaNf && row.conteudoDaNf.trim() !== ''
|
|
? row.conteudoDaNf.trim()
|
|
: '(Sem Conteúdo)';
|
|
|
|
if (!groupsMap.has(key)) groupsMap.set(key, []);
|
|
groupsMap.get(key)?.push(row);
|
|
});
|
|
|
|
this.controleGroups = [];
|
|
groupsMap.forEach((items, key) => {
|
|
this.controleGroups.push({ conteudo: key, total: items.length, items });
|
|
});
|
|
|
|
this.controleGroups.sort((a, b) => a.conteudo.localeCompare(b.conteudo));
|
|
this.expandedControleConteudo = null;
|
|
}
|
|
|
|
private applyControlePagination() {
|
|
const start = (this.controlePage - 1) * this.controlePageSize;
|
|
const end = start + this.controlePageSize;
|
|
this.pagedControleGroups = this.controleGroups.slice(start, end);
|
|
|
|
if (this.expandedControleConteudo && !this.pagedControleGroups.some(g => g.conteudo === this.expandedControleConteudo)) {
|
|
this.expandedControleConteudo = null;
|
|
}
|
|
}
|
|
|
|
toggleControleGroup(conteudo: string) {
|
|
this.expandedControleConteudo = this.expandedControleConteudo === conteudo ? null : conteudo;
|
|
}
|
|
|
|
openControleDetail(row: ControleRecebidoListDto) {
|
|
if (!row?.id) return;
|
|
this.controleDetailOpen = true;
|
|
this.controleDetailLoading = true;
|
|
this.controleDetailData = null;
|
|
|
|
this.service.getControleRecebidoById(row.id).subscribe({
|
|
next: (data) => {
|
|
this.controleDetailData = data ?? row;
|
|
this.controleDetailLoading = false;
|
|
},
|
|
error: () => {
|
|
this.controleDetailLoading = false;
|
|
this.controleDetailData = row;
|
|
}
|
|
});
|
|
}
|
|
|
|
openControleCreate() {
|
|
if (!this.isAdmin) return;
|
|
this.controleCreateModel = {
|
|
id: '',
|
|
ano: new Date().getFullYear(),
|
|
item: null,
|
|
notaFiscal: '',
|
|
chip: '',
|
|
serial: '',
|
|
conteudoDaNf: '',
|
|
numeroDaLinha: '',
|
|
valorUnit: null,
|
|
valorDaNf: null,
|
|
dataDaNf: null,
|
|
dataDoRecebimento: null,
|
|
quantidade: null,
|
|
isResumo: false
|
|
} as ControleRecebidoListDto;
|
|
this.controleCreateDataNf = '';
|
|
this.controleCreateRecebimento = '';
|
|
this.controleCreateOpen = true;
|
|
this.controleCreateSaving = false;
|
|
}
|
|
|
|
closeControleCreate() {
|
|
this.controleCreateOpen = false;
|
|
this.controleCreateSaving = false;
|
|
this.controleCreateModel = null;
|
|
this.controleCreateDataNf = '';
|
|
this.controleCreateRecebimento = '';
|
|
}
|
|
|
|
onControleCreateValueChange() {
|
|
if (!this.controleCreateModel) return;
|
|
this.recalculateControleTotals(this.controleCreateModel);
|
|
}
|
|
|
|
onControleEditValueChange() {
|
|
if (!this.controleEditModel) return;
|
|
this.recalculateControleTotals(this.controleEditModel);
|
|
}
|
|
|
|
onControleCreateDateChange() {
|
|
if (!this.controleCreateModel) return;
|
|
if (!this.controleCreateModel.ano && this.controleCreateDataNf) {
|
|
const year = new Date(this.controleCreateDataNf).getFullYear();
|
|
if (Number.isFinite(year)) this.controleCreateModel.ano = year;
|
|
}
|
|
}
|
|
|
|
onControleEditDateChange() {
|
|
if (!this.controleEditModel) return;
|
|
if (!this.controleEditModel.ano && this.controleEditDataNf) {
|
|
const year = new Date(this.controleEditDataNf).getFullYear();
|
|
if (Number.isFinite(year)) this.controleEditModel.ano = year;
|
|
}
|
|
}
|
|
|
|
private recalculateControleTotals(model: ControleRecebidoListDto) {
|
|
const quantidade = this.toNullableNumber(model.quantidade);
|
|
const valorUnit = this.toNullableNumber(model.valorUnit);
|
|
const valorDaNf = this.toNullableNumber(model.valorDaNf);
|
|
|
|
if (quantidade != null && valorUnit != null && (valorDaNf == null || valorDaNf === 0)) {
|
|
model.valorDaNf = Number((valorUnit * quantidade).toFixed(2));
|
|
} else if (quantidade != null && valorDaNf != null && (valorUnit == null || valorUnit === 0)) {
|
|
model.valorUnit = Number((valorDaNf / quantidade).toFixed(2));
|
|
}
|
|
}
|
|
|
|
saveControleCreate() {
|
|
if (!this.controleCreateModel) return;
|
|
this.recalculateControleTotals(this.controleCreateModel);
|
|
this.controleCreateSaving = true;
|
|
|
|
const payload: CreateControleRecebidoRequest = {
|
|
ano: this.toNullableNumber(this.controleCreateModel.ano),
|
|
item: this.toNullableNumber(this.controleCreateModel.item),
|
|
notaFiscal: this.controleCreateModel.notaFiscal,
|
|
chip: this.controleCreateModel.chip,
|
|
serial: this.controleCreateModel.serial,
|
|
conteudoDaNf: this.controleCreateModel.conteudoDaNf,
|
|
numeroDaLinha: this.controleCreateModel.numeroDaLinha,
|
|
valorUnit: this.toNullableNumber(this.controleCreateModel.valorUnit),
|
|
valorDaNf: this.toNullableNumber(this.controleCreateModel.valorDaNf),
|
|
dataDaNf: this.dateInputToIso(this.controleCreateDataNf),
|
|
dataDoRecebimento: this.dateInputToIso(this.controleCreateRecebimento),
|
|
quantidade: this.toNullableNumber(this.controleCreateModel.quantidade),
|
|
isResumo: this.controleCreateModel.isResumo ?? false
|
|
};
|
|
|
|
this.service.createControleRecebido(payload).subscribe({
|
|
next: () => {
|
|
this.controleCreateSaving = false;
|
|
this.closeControleCreate();
|
|
this.fetchControle();
|
|
this.showToast('Recebimento criado com sucesso!', 'success');
|
|
},
|
|
error: () => {
|
|
this.controleCreateSaving = false;
|
|
this.showToast('Erro ao criar recebimento.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
openControleEdit(row: ControleRecebidoListDto) {
|
|
if (!this.isAdmin) return;
|
|
this.service.getControleRecebidoById(row.id).subscribe({
|
|
next: (data) => {
|
|
this.controleEditingId = data.id;
|
|
this.controleEditModel = { ...data };
|
|
this.controleEditDataNf = this.toDateInput(data.dataDaNf);
|
|
this.controleEditRecebimento = this.toDateInput(data.dataDoRecebimento);
|
|
this.controleEditOpen = true;
|
|
},
|
|
error: () => this.showToast('Erro ao abrir edição.', 'danger')
|
|
});
|
|
}
|
|
|
|
closeControleEdit() {
|
|
this.controleEditOpen = false;
|
|
this.controleEditSaving = false;
|
|
this.controleEditModel = null;
|
|
this.controleEditDataNf = '';
|
|
this.controleEditRecebimento = '';
|
|
this.controleEditingId = null;
|
|
}
|
|
|
|
saveControleEdit() {
|
|
if (!this.controleEditModel || !this.controleEditingId) return;
|
|
this.recalculateControleTotals(this.controleEditModel);
|
|
this.controleEditSaving = true;
|
|
const payload: UpdateControleRecebidoRequest = {
|
|
ano: this.toNullableNumber(this.controleEditModel.ano),
|
|
item: this.toNullableNumber(this.controleEditModel.item),
|
|
notaFiscal: this.controleEditModel.notaFiscal,
|
|
chip: this.controleEditModel.chip,
|
|
serial: this.controleEditModel.serial,
|
|
conteudoDaNf: this.controleEditModel.conteudoDaNf,
|
|
numeroDaLinha: this.controleEditModel.numeroDaLinha,
|
|
valorUnit: this.toNullableNumber(this.controleEditModel.valorUnit),
|
|
valorDaNf: this.toNullableNumber(this.controleEditModel.valorDaNf),
|
|
dataDaNf: this.dateInputToIso(this.controleEditDataNf),
|
|
dataDoRecebimento: this.dateInputToIso(this.controleEditRecebimento),
|
|
quantidade: this.toNullableNumber(this.controleEditModel.quantidade),
|
|
isResumo: this.controleEditModel.isResumo ?? false
|
|
};
|
|
this.service.updateControleRecebido(this.controleEditingId, payload).subscribe({
|
|
next: () => {
|
|
this.controleEditSaving = false;
|
|
this.closeControleEdit();
|
|
this.fetchControle();
|
|
this.showToast('Registro atualizado!', 'success');
|
|
},
|
|
error: () => {
|
|
this.controleEditSaving = false;
|
|
this.showToast('Erro ao salvar.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
openControleDelete(row: ControleRecebidoListDto) {
|
|
if (!this.isAdmin) return;
|
|
this.controleDeleteTarget = row;
|
|
this.controleDeleteOpen = true;
|
|
}
|
|
|
|
cancelControleDelete() {
|
|
this.controleDeleteOpen = false;
|
|
this.controleDeleteTarget = null;
|
|
}
|
|
|
|
confirmControleDelete() {
|
|
if (!this.controleDeleteTarget) return;
|
|
const id = this.controleDeleteTarget.id;
|
|
this.service.removeControleRecebido(id).subscribe({
|
|
next: () => {
|
|
this.controleDeleteOpen = false;
|
|
this.controleDeleteTarget = null;
|
|
this.fetchControle();
|
|
this.showToast('Registro removido.', 'success');
|
|
},
|
|
error: () => {
|
|
this.controleDeleteOpen = false;
|
|
this.controleDeleteTarget = null;
|
|
this.showToast('Erro ao remover.', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
private toDateInput(value: string | null): string {
|
|
if (!value) return '';
|
|
const d = new Date(value);
|
|
if (isNaN(d.getTime())) return '';
|
|
return d.toISOString().slice(0, 10);
|
|
}
|
|
|
|
private dateInputToIso(value: string): string | null {
|
|
if (!value) return null;
|
|
const d = new Date(`${value}T00:00:00`);
|
|
if (isNaN(d.getTime())) return null;
|
|
return d.toISOString();
|
|
}
|
|
|
|
private toNullableNumber(value: any): number | null {
|
|
if (value === undefined || value === null || value === '') return null;
|
|
const n = Number(value);
|
|
return Number.isNaN(n) ? null : n;
|
|
}
|
|
|
|
closeControleDetail() {
|
|
this.controleDetailOpen = false;
|
|
this.controleDetailLoading = false;
|
|
this.controleDetailData = null;
|
|
}
|
|
|
|
// =====================
|
|
// Paginação e Helpers
|
|
// =====================
|
|
get activePage() { return this.activeTab === 'chips' ? this.chipsPage : this.controlePage; }
|
|
get activeTotal() { return this.activeTab === 'chips' ? this.chipsTotal : this.controleTotal; }
|
|
get activePageSize() { return this.activeTab === 'chips' ? this.chipsPageSize : this.controlePageSize; }
|
|
get activeTotalPages() { return Math.max(1, Math.ceil((this.activeTotal || 0) / (this.activePageSize || 10))); }
|
|
|
|
get activePageStart() { return this.activeTotal === 0 ? 0 : (this.activePage - 1) * this.activePageSize + 1; }
|
|
get activePageEnd() { return this.activeTotal === 0 ? 0 : Math.min(this.activePage * this.activePageSize, this.activeTotal); }
|
|
|
|
get activeLoading() { return this.activeTab === 'chips' ? this.chipsLoading : this.controleLoading; } // ✅ novo
|
|
|
|
get activePageNumbers() {
|
|
const total = this.activeTotalPages;
|
|
const current = this.activePage;
|
|
const max = 5;
|
|
let start = Math.max(1, current - 2);
|
|
let end = Math.min(total, start + (max - 1));
|
|
start = Math.max(1, end - (max - 1));
|
|
const pages = [];
|
|
for (let i = start; i <= end; i++) pages.push(i);
|
|
return pages;
|
|
}
|
|
|
|
goToPage(p: number) {
|
|
const target = Math.max(1, Math.min(this.activeTotalPages, p));
|
|
|
|
if (this.activeTab === 'chips') {
|
|
this.chipsPage = target;
|
|
this.applyChipsPagination();
|
|
} else {
|
|
this.controlePage = target;
|
|
this.applyControlePagination();
|
|
}
|
|
}
|
|
|
|
normalizeChip(x: any, idx: number): ChipVirgemListDto {
|
|
return {
|
|
id: String(x.id || idx),
|
|
item: Number(x.item || 0),
|
|
numeroDoChip: x.numeroDoChip || x.NumeroDoChip,
|
|
observacoes: x.observacoes || x.Observacoes
|
|
};
|
|
}
|
|
|
|
normalizeControle(x: any, idx: number): ControleRecebidoListDto {
|
|
return {
|
|
id: String(x.id || idx),
|
|
ano: x.ano,
|
|
item: x.item,
|
|
notaFiscal: x.notaFiscal,
|
|
chip: x.chip,
|
|
serial: x.serial,
|
|
conteudoDaNf: x.conteudoDaNf,
|
|
numeroDaLinha: x.numeroDaLinha,
|
|
valorUnit: x.valorUnit,
|
|
valorDaNf: x.valorDaNf,
|
|
dataDaNf: x.dataDaNf,
|
|
dataDoRecebimento: x.dataDoRecebimento,
|
|
quantidade: x.quantidade,
|
|
isResumo: x.isResumo
|
|
};
|
|
}
|
|
|
|
display(val: any) { return val ? String(val) : '-'; }
|
|
formatMoney(val: any) {
|
|
if (!val) return '-';
|
|
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(val);
|
|
}
|
|
formatDate(val: any) { if (!val) return '-'; return new Date(val).toLocaleDateString('pt-BR'); }
|
|
isResumo(r: any) { return !!r.isResumo; }
|
|
getResumoItems(items: ControleRecebidoListDto[]) { return (items || []).filter(r => this.isResumo(r)); }
|
|
getDetalheItems(items: ControleRecebidoListDto[]) { return (items || []).filter(r => !this.isResumo(r)); }
|
|
trackById(idx: number, item: any) { return item.id; }
|
|
|
|
showToast(msg: string, type: 'success' | 'danger') {
|
|
this.toastMessage = msg;
|
|
this.toastType = type;
|
|
this.toastOpen = true;
|
|
setTimeout(() => this.toastOpen = false, 3000);
|
|
}
|
|
}
|