| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- <template>
- <q-dialog ref="dialogRef" @hide="onDialogHide">
- <q-card
- class="q-dialog-plugin overflow-hidden"
- style="width: 100%; max-width: 1100px"
- >
- <DefaultDialogHeader title="Criar novo contrato" @close="onDialogCancel" />
- <DefaultForm ref="formRef" @submit="onSubmit">
- <q-scroll-area ref="scrollAreaRef" class="form-dialog-scroll-area">
- <q-card-section class="row q-col-gutter-md q-pt-none">
- <div class="col-12 text-body2">
- Dados da Unidade
- </div>
- <DefaultInput
- class="col-12 col-md-6"
- color="secondary"
- label="Nome da Unidade"
- label-color="secondary"
- readonly
- :model-value="unitData.name"
- />
- <DefaultInput
- class="col-12 col-md-3"
- color="secondary"
- label="CNPJ"
- label-color="secondary"
- readonly
- :mask="masks.Brasil.cnpj"
- :model-value="unitData.cnpj"
- :rules="[inputRules.cnpj]"
- />
- <DefaultInput
- class="col-12 col-md-3"
- color="secondary"
- disable
- label="ID"
- label-color="secondary"
- :model-value="unitData.id"
- />
- <DefaultInput
- class="col-12 col-md-4"
- color="secondary"
- disable
- label="Nome do Franqueado"
- label-color="secondary"
- :model-value="unitData.franchisee_name"
- />
- <DefaultInput
- class="col-12 col-md-4"
- color="secondary"
- disable
- label="CPF"
- label-color="secondary"
- :mask="masks.Brasil.cpf"
- :model-value="unitData.franchisee_document"
- :rules="[inputRules.cpf]"
- />
- <DefaultInput
- class="col-12 col-md-4"
- color="secondary"
- disable
- label="Data de Nascimento"
- label-color="secondary"
- :model-value="unitData.franchisee_birthday"
- />
- <div class="col-12 text-body2 q-mt-sm">
- Definir Valores e TBR
- </div>
- <DefaultInputDatePicker
- v-model:untreated-date="form.start_date"
- v-model:error="validationErrors.start_date"
- class="col-12 col-md-3"
- color="secondary"
- label="Data de Início"
- label-color="secondary"
- :error-message="validationErrors.start_date"
- :rules="[inputRules.required]"
- />
- <DefaultInputDatePicker
- v-model:untreated-date="form.end_date"
- v-model:error="validationErrors.end_date"
- class="col-12 col-md-3"
- color="secondary"
- label="Data de Fim"
- label-color="secondary"
- :error-message="validationErrors.end_date"
- :rules="[inputRules.required, endDateRule]"
- />
- <DefaultCurrencyInput
- v-model="form.tbr_fixed_value"
- v-model:error="validationErrors.tbr_fixed_value"
- class="col-12 col-md-3"
- color="secondary"
- label="TBR $"
- label-color="secondary"
- :error-message="validationErrors.tbr_fixed_value"
- :rules="[requiredNumberRule]"
- />
- <DefaultInput
- v-model="form.invoice_due_date"
- v-model:error="validationErrors.invoice_due_date"
- class="col-12 col-md-3"
- color="secondary"
- label="Dia de Vencimento do Boleto"
- label-color="secondary"
- max="31"
- min="1"
- type="number"
- :error-message="validationErrors.invoice_due_date"
- :rules="[invoiceDueDateRule]"
- />
- <DefaultSelect
- v-model="form.municipality_size_id"
- v-model:error="validationErrors.municipality_size_id"
- class="col-12 col-md-3"
- color="secondary"
- emit-value
- fill-input
- hide-selected
- input-debounce="0"
- label="Faixa de Habitante"
- label-color="secondary"
- map-options
- use-input
- :error-message="validationErrors.municipality_size_id"
- :options="municipalitySizeOptions"
- >
- <template #no-option>
- <q-item>
- <q-item-section class="text-grey">
- {{ $t("http.errors.no_records_found") }}
- </q-item-section>
- </q-item>
- </template>
- </DefaultSelect>
- <DefaultInput
- v-model="form.tax_base_royalts"
- v-model:error="validationErrors.tbr_fixed_value_percentage"
- class="col-12 col-md-3"
- color="secondary"
- label="Taxa Base Royalties"
- label-color="secondary"
- max="100"
- min="0"
- type="number"
- :error-message="validationErrors.tbr_fixed_value_percentage"
- :rules="percentageRules"
- >
- <template #append>
- <span class="text-secondary">%</span>
- </template>
- </DefaultInput>
- <DefaultInput
- v-model="form.tax_base_fnm"
- v-model:error="validationErrors.marketing_fund_percentage"
- class="col-12 col-md-3"
- color="secondary"
- label="Taxa Base FMN"
- label-color="secondary"
- max="100"
- min="0"
- type="number"
- :error-message="validationErrors.marketing_fund_percentage"
- :rules="percentageRules"
- >
- <template #append>
- <span class="text-secondary">%</span>
- </template>
- </DefaultInput>
- <DefaultInput
- v-model="form.tax_base_maintenance"
- v-model:error="validationErrors.maintance_tax_percentage"
- class="col-12 col-md-3"
- color="secondary"
- label="Taxa Base Manutenção"
- label-color="secondary"
- max="100"
- min="0"
- type="number"
- :error-message="validationErrors.maintance_tax_percentage"
- :rules="percentageRules"
- >
- <template #append>
- <span class="text-secondary">%</span>
- </template>
- </DefaultInput>
- </q-card-section>
- </q-scroll-area>
- <q-separator />
- <q-card-actions align="right" class="q-pa-md q-gutter-sm">
- <q-btn
- color="negative"
- label="Cancelar"
- no-caps
- outline
- @click="onDialogCancel"
- />
- <q-btn
- color="primary"
- label="Salvar"
- no-caps
- type="submit"
- unelevated
- :loading="loading"
- />
- </q-card-actions>
- </DefaultForm>
- </q-card>
- </q-dialog>
- </template>
- <script setup>
- import { createFranchiseeContract } from "src/api/franchisee_contract";
- import { getLatestTbr } from "src/api/tbr";
- import { getMunicipalitySizes } from "src/api/tbr_calculation";
- import { getUnit } from "src/api/unit";
- import { onMounted, reactive, ref } from "vue";
- import { useDialogPluginComponent } from "quasar";
- import { useForm } from "src/composables/useForm";
- import { useInputRules } from "src/composables/useInputRules";
- import { useScroll } from "src/composables/useScroll";
- import { useSubmitHandler } from "src/composables/useSubmitHandler";
- import masks from "src/helpers/masks";
- import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
- import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
- import DefaultForm from "src/components/defaults/DefaultForm.vue";
- import DefaultInput from "src/components/defaults/DefaultInput.vue";
- import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
- import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
- defineEmits([...useDialogPluginComponent.emits]);
- const props = defineProps({
- unitId: {
- required: true,
- type: Number,
- },
- });
- const { dialogRef, onDialogCancel, onDialogHide, onDialogOK } =
- useDialogPluginComponent();
- const { inputRules } = useInputRules();
- const formRef = ref(null);
- const scrollAreaRef = ref(null);
- const { scrollToComponent } = useScroll();
- const { form } = useForm(
- {
- end_date: null,
- invoice_due_date: null,
- municipality_size_id: null,
- start_date: null,
- tax_base_fnm: null,
- tax_base_maintenance: null,
- tax_base_royalts: null,
- tbr_fixed_value: null,
- },
- { containerRef: scrollAreaRef },
- );
- const {
- loading,
- validationErrors,
- execute,
- } = useSubmitHandler({
- containerRef: scrollAreaRef,
- formRef,
- onSuccess: (result) => onDialogOK(result),
- scrollFn: scrollToComponent,
- });
- const unitData = reactive({
- cnpj: null,
- franchisee_birthday: null,
- franchisee_document: null,
- franchisee_name: null,
- id: null,
- name: null,
- });
- const municipalitySizeOptions = ref([]);
- const percentageRules = [
- inputRules.minValue(0),
- inputRules.maxValue(100),
- ];
- // form.start_date/form.end_date são o "untreated-date" do DefaultInputDatePicker
- // (formato YYYY-MM-DD), então comparam corretamente como string. O "value" que o
- // q-input passa pra regra é o "treated-date" (DD/MM/YYYY) do campo — formato
- // diferente de form.start_date, o que fazia a comparação dar falso positivo.
- const endDateRule = () =>
- !form.end_date ||
- !form.start_date ||
- form.end_date > form.start_date ||
- "A data de fim deve ser posterior à data de início";
- const invoiceDueDateRule = (value) =>
- value === null ||
- value === undefined ||
- value === "" ||
- (Number.isInteger(Number(value)) &&
- Number(value) >= 1 &&
- Number(value) <= 31) ||
- "O dia de vencimento deve ser um número inteiro entre 1 e 31";
- const loadData = async () => {
- const [unit, latestTbr, sizes] = await Promise.all([
- getUnit(props.unitId),
- getLatestTbr(),
- getMunicipalitySizes(),
- ]);
- unitData.cnpj = unit.cnpj;
- unitData.franchisee_name = unit.name_responsible;
- unitData.id = unit.id;
- unitData.name = unit.name;
- const firstPartner = unit.partners?.[0];
- if (firstPartner) {
- unitData.franchisee_birthday = firstPartner.birth_date;
- unitData.franchisee_document = firstPartner.cpf;
- }
- if (latestTbr) {
- form.tax_base_fnm = parseFloat(
- (latestTbr.fnm_percentage * 100).toFixed(4),
- );
- form.tax_base_maintenance = parseFloat(
- (latestTbr.maintenance_percentage * 100).toFixed(4),
- );
- form.tax_base_royalts = parseFloat(
- (latestTbr.royalties_percentage * 100).toFixed(4),
- );
- form.tbr_fixed_value = parseFloat(latestTbr.tbr_value);
- }
- municipalitySizeOptions.value = (sizes ?? []).map((size) => ({
- label: size.description,
- value: size.id,
- }));
- };
- const onSubmit = async () => {
- await execute(() =>
- createFranchiseeContract({
- end_date: form.end_date,
- invoice_due_date: form.invoice_due_date,
- maintance_tax_percentage:
- form.tax_base_maintenance != null
- ? form.tax_base_maintenance / 100
- : null,
- marketing_fund_percentage:
- form.tax_base_fnm != null ? form.tax_base_fnm / 100 : null,
- municipality_size_id: form.municipality_size_id,
- start_date: form.start_date,
- tbr_fixed_value: form.tbr_fixed_value,
- tbr_fixed_value_percentage:
- form.tax_base_royalts != null ? form.tax_base_royalts / 100 : null,
- unit_id: props.unitId,
- }),
- );
- };
- const requiredNumberRule = (value) =>
- (value !== null && value !== undefined && value !== "") ||
- inputRules.required(null);
- requiredNumberRule.$id = "required";
- onMounted(loadData);
- </script>
|