CreateContractDialog.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. <template>
  2. <q-dialog ref="dialogRef" @hide="onDialogHide">
  3. <q-card
  4. class="q-dialog-plugin overflow-hidden"
  5. style="width: 100%; max-width: 1100px"
  6. >
  7. <DefaultDialogHeader
  8. :title="'Criar novo contrato'"
  9. @close="onDialogCancel"
  10. />
  11. <q-card-section>
  12. <div class="text-body2 q-mb-sm">Dados da Unidade</div>
  13. <div class="row q-col-gutter-sm">
  14. <DefaultInput
  15. :model-value="unitData.name"
  16. label="Nome da Unidade"
  17. color="secondary"
  18. label-color="secondary"
  19. class="col-md-6 col-12"
  20. readonly
  21. />
  22. <DefaultInput
  23. :model-value="unitData.cnpj"
  24. label="CNPJ"
  25. color="secondary"
  26. label-color="secondary"
  27. class="col-md-3 col-12"
  28. :mask="masks.Brasil.cnpj"
  29. :rules="[inputRules.cnpj]"
  30. readonly
  31. />
  32. <DefaultInput
  33. :model-value="unitData.id"
  34. label="ID"
  35. color="secondary"
  36. label-color="secondary"
  37. class="col-md-3 col-12"
  38. disable
  39. />
  40. <DefaultInput
  41. :model-value="unitData.franchisee_name"
  42. label="Nome do Franqueado"
  43. color="secondary"
  44. label-color="secondary"
  45. class="col-md-4 col-12"
  46. disable
  47. />
  48. <DefaultInput
  49. :model-value="unitData.franchisee_document"
  50. label="CPF"
  51. color="secondary"
  52. label-color="secondary"
  53. class="col-md-4 col-12"
  54. :mask="masks.Brasil.cpf"
  55. disable
  56. />
  57. <DefaultInput
  58. :model-value="unitData.franchisee_birthday"
  59. label="Data de Nascimento"
  60. color="secondary"
  61. label-color="secondary"
  62. class="col-md-4 col-12"
  63. disable
  64. />
  65. </div>
  66. </q-card-section>
  67. <q-card-section>
  68. <div class="text-body2 q-mb-sm">Definir Valores e TBR</div>
  69. <div class="row q-col-gutter-sm">
  70. <DefaultInputDatePicker
  71. v-model:untreated-date="contractForm.start_date"
  72. label="Data de Início"
  73. color="secondary"
  74. label-color="secondary"
  75. class="col-md-3 col-12"
  76. />
  77. <DefaultInputDatePicker
  78. v-model:untreated-date="contractForm.end_date"
  79. label="Data de Fim"
  80. color="secondary"
  81. label-color="secondary"
  82. class="col-md-3 col-12"
  83. />
  84. <DefaultCurrencyInput
  85. v-model="contractForm.tbr_fixed_value"
  86. label="TBR $"
  87. color="secondary"
  88. label-color="secondary"
  89. class="col-md-3 col-12"
  90. />
  91. <DefaultInput
  92. v-model="contractForm.invoice_due_date"
  93. label="Dia de Vencimento do Boleto"
  94. color="secondary"
  95. label-color="secondary"
  96. type="number"
  97. class="col-md-3 col-12"
  98. >
  99. </DefaultInput>
  100. <DefaultSelect
  101. v-model="contractForm.municipality_size_id"
  102. label="Faixa de Habitante"
  103. color="secondary"
  104. label-color="secondary"
  105. :options="municipalitySizeOptions"
  106. emit-value
  107. map-options
  108. use-input
  109. fill-input
  110. hide-selected
  111. input-debounce="0"
  112. class="col-md-3 col-12"
  113. />
  114. <DefaultInput
  115. v-model="contractForm.tax_base_royalts"
  116. label="Taxa Base Royalties"
  117. color="secondary"
  118. label-color="secondary"
  119. type="number"
  120. class="col-md-3 col-12"
  121. >
  122. <template #append>
  123. <span class="text-secondary">%</span>
  124. </template>
  125. </DefaultInput>
  126. <DefaultInput
  127. v-model="contractForm.tax_base_fnm"
  128. label="Taxa Base FMN"
  129. color="secondary"
  130. label-color="secondary"
  131. type="number"
  132. class="col-md-3 col-12"
  133. >
  134. <template #append>
  135. <span class="text-secondary">%</span>
  136. </template>
  137. </DefaultInput>
  138. <DefaultInput
  139. v-model="contractForm.tax_base_maintenance"
  140. label="Taxa Base Manutenção"
  141. color="secondary"
  142. label-color="secondary"
  143. type="number"
  144. class="col-md-3 col-12"
  145. >
  146. <template #append>
  147. <span class="text-secondary">%</span>
  148. </template>
  149. </DefaultInput>
  150. </div>
  151. </q-card-section>
  152. <q-card-actions align="right">
  153. <q-btn
  154. outline
  155. color="primary"
  156. label="Cancelar"
  157. @click="onDialogCancel"
  158. />
  159. <q-btn color="primary" label="Salvar" :loading="saving" @click="save" />
  160. </q-card-actions>
  161. </q-card>
  162. </q-dialog>
  163. </template>
  164. <script setup>
  165. import { ref, reactive, onMounted } from "vue";
  166. import { useDialogPluginComponent } from "quasar";
  167. import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
  168. import DefaultInput from "src/components/defaults/DefaultInput.vue";
  169. import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
  170. import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
  171. import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
  172. import masks from "src/helpers/masks";
  173. import { useInputRules } from "src/composables/useInputRules";
  174. import { getUnit } from "src/api/unit";
  175. import { getLatestTbr } from "src/api/tbr";
  176. import { getMunicipalitySizes } from "src/api/tbr_calculation";
  177. import { createFranchiseeContract } from "src/api/franchisee_contract";
  178. defineEmits([...useDialogPluginComponent.emits]);
  179. const props = defineProps({
  180. unitId: {
  181. type: Number,
  182. required: true,
  183. },
  184. });
  185. const { dialogRef, onDialogHide, onDialogCancel, onDialogOK } =
  186. useDialogPluginComponent();
  187. const saving = ref(false);
  188. const municipalitySizeOptions = ref([]);
  189. const { inputRules } = useInputRules();
  190. const unitData = reactive({
  191. id: null,
  192. name: null,
  193. cnpj: null,
  194. franchisee_name: null,
  195. franchisee_document: null,
  196. franchisee_birthday: null,
  197. });
  198. const contractForm = reactive({
  199. start_date: null,
  200. end_date: null,
  201. tbr_fixed_value: null,
  202. invoice_due_date: null,
  203. municipality_size_id: null,
  204. tax_base_royalts: null,
  205. tax_base_fnm: null,
  206. tax_base_maintenance: null,
  207. });
  208. async function loadData() {
  209. const [unit, latestTbr, sizes] = await Promise.all([
  210. getUnit(props.unitId),
  211. getLatestTbr(),
  212. getMunicipalitySizes(),
  213. ]);
  214. unitData.id = unit.id;
  215. unitData.name = unit.name;
  216. unitData.cnpj = unit.cnpj;
  217. unitData.franchisee_name = unit.name_responsible;
  218. const firstPartner = unit.partners?.[0];
  219. if (firstPartner) {
  220. unitData.franchisee_document = firstPartner.cpf;
  221. unitData.franchisee_birthday = firstPartner.birth_date;
  222. }
  223. if (latestTbr) {
  224. contractForm.tbr_fixed_value = parseFloat(latestTbr.tbr_value);
  225. contractForm.tax_base_royalts = parseFloat(
  226. (latestTbr.royalties_percentage * 100).toFixed(4),
  227. );
  228. contractForm.tax_base_fnm = parseFloat(
  229. (latestTbr.fnm_percentage * 100).toFixed(4),
  230. );
  231. contractForm.tax_base_maintenance = parseFloat(
  232. (latestTbr.maintenance_percentage * 100).toFixed(4),
  233. );
  234. }
  235. municipalitySizeOptions.value = (sizes ?? []).map((s) => ({
  236. label: s.description,
  237. value: s.id,
  238. }));
  239. }
  240. async function save() {
  241. saving.value = true;
  242. try {
  243. await createFranchiseeContract({
  244. unit_id: props.unitId,
  245. start_date: contractForm.start_date,
  246. end_date: contractForm.end_date,
  247. tbr_fixed_value: contractForm.tbr_fixed_value,
  248. invoice_due_date: contractForm.invoice_due_date,
  249. municipality_size_id: contractForm.municipality_size_id,
  250. tbr_fixed_value_percentage:
  251. contractForm.tax_base_royalts != null
  252. ? contractForm.tax_base_royalts / 100
  253. : null,
  254. marketing_fund_percentage:
  255. contractForm.tax_base_fnm != null
  256. ? contractForm.tax_base_fnm / 100
  257. : null,
  258. maintance_tax_percentage:
  259. contractForm.tax_base_maintenance != null
  260. ? contractForm.tax_base_maintenance / 100
  261. : null,
  262. });
  263. onDialogOK();
  264. } catch (error) {
  265. console.error(error);
  266. } finally {
  267. saving.value = false;
  268. }
  269. }
  270. onMounted(loadData);
  271. </script>