Some AMP, some postgres(liek working DECIMAL) improvements.
This commit is contained in:
parent
41f046624d
commit
817c0d9d32
|
|
@ -60,7 +60,7 @@ namespace NejCommon.Controllers
|
||||||
var endpointBuilder = new MetadataEndpointBuilder();
|
var endpointBuilder = new MetadataEndpointBuilder();
|
||||||
populateMetadataMethod.Invoke(null, new object[] { context.MethodInfo, endpointBuilder });
|
populateMetadataMethod.Invoke(null, new object[] { context.MethodInfo, endpointBuilder });
|
||||||
|
|
||||||
var responseTypes = endpointBuilder.Metadata.Cast<IProducesResponseTypeMetadata>().ToList();
|
var responseTypes = endpointBuilder.Metadata.OfType<IProducesResponseTypeMetadata>().ToList();
|
||||||
if (!responseTypes.Any()) return;
|
if (!responseTypes.Any()) return;
|
||||||
operation.Responses.Clear();
|
operation.Responses.Clear();
|
||||||
foreach (var responseType in responseTypes)
|
foreach (var responseType in responseTypes)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
! tailwindcss v3.4.15 | MIT License | https://tailwindcss.com
|
! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
/* 2 */
|
/* 2 */
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
/* 2 */
|
/* 2 */
|
||||||
border-color: #e5e7eb;
|
border-color: currentColor;
|
||||||
/* 2 */
|
/* 2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,7 +415,7 @@ video {
|
||||||
|
|
||||||
/* Make elements with the HTML hidden attribute stay hidden by default */
|
/* Make elements with the HTML hidden attribute stay hidden by default */
|
||||||
|
|
||||||
[hidden]:where(:not([hidden="until-found"])) {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,18 +513,38 @@ video {
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
.static {
|
.static {
|
||||||
position: static;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fixed {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
.absolute {
|
.absolute {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.m-0 {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.ml-2 {
|
.ml-2 {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.inline {
|
.inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
@ -553,6 +573,22 @@ video {
|
||||||
height: 12rem;
|
height: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-10 {
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-3 {
|
||||||
|
height: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-2 {
|
||||||
|
height: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-5 {
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
@ -565,10 +601,34 @@ video {
|
||||||
width: 12rem;
|
width: 12rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-10 {
|
||||||
|
width: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-2 {
|
||||||
|
width: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-5 {
|
||||||
|
width: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-\[680px\] {
|
||||||
|
max-width: 680px;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-grow {
|
.flex-grow {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-fixed {
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transform {
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
.flex-col {
|
.flex-col {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
@ -605,6 +665,14 @@ video {
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.break-all {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded-md {
|
.rounded-md {
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
@ -613,6 +681,26 @@ video {
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rounded-2xl {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-xl {
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-sm {
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
.border-4 {
|
.border-4 {
|
||||||
border-width: 4px;
|
border-width: 4px;
|
||||||
}
|
}
|
||||||
|
|
@ -621,11 +709,133 @@ video {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-t {
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-r {
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-b {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-line {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(41 55 71 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-neon {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(76 227 90 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-line-soft {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(27 41 54 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-neon-soft {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(21 56 32 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-red-soft {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(58 23 26 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-email-yellow-soft {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 48 18 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(var(--primary) / var(--tw-bg-opacity));
|
background-color: rgb(var(--primary) / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-email-canvas {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(7 11 16 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-header {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(8 17 28 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-neon-soft {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(21 56 32 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-surface {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(13 21 30 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-surface-2 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(17 28 39 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-line-soft {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(27 41 54 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-red {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(240 82 82 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-neon {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(76 227 90 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-blue {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-blue-2 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-slate-bar {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(122 135 149 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-purple {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(139 92 246 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-yellow {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(251 191 36 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-orange {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 115 22 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-red-soft {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(58 23 26 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-email-yellow-soft {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(59 48 18 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.py-2 {
|
.py-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
|
@ -641,6 +851,66 @@ video {
|
||||||
padding-right: 2.5rem;
|
padding-right: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.px-3 {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-6 {
|
||||||
|
padding-top: 1.5rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-7 {
|
||||||
|
padding-left: 1.75rem;
|
||||||
|
padding-right: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-5 {
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
padding-right: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-2 {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-3 {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-2\.5 {
|
||||||
|
padding-top: 0.625rem;
|
||||||
|
padding-bottom: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-1 {
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-0\.5 {
|
||||||
|
padding-top: 0.125rem;
|
||||||
|
padding-bottom: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-0 {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-1\.5 {
|
||||||
|
padding-top: 0.375rem;
|
||||||
|
padding-bottom: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pt-2 {
|
.pt-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
@ -665,10 +935,74 @@ video {
|
||||||
padding-top: 0.25rem;
|
padding-top: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pl-3 {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-5 {
|
||||||
|
padding-top: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-4 {
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-1\.5 {
|
||||||
|
padding-right: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-1 {
|
||||||
|
padding-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-2 {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-1\.5 {
|
||||||
|
padding-left: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-1 {
|
||||||
|
padding-left: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-3 {
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-4 {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-4 {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-3 {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-3 {
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-left {
|
.text-left {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-middle {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-email {
|
||||||
|
font-family: Trebuchet MS, Segoe UI, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
.text-sm {
|
.text-sm {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
|
|
@ -699,6 +1033,46 @@ video {
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-\[11px\] {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[28px\] {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[14px\] {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[13px\] {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[22px\] {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[10px\] {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[9px\] {
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[24px\] {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[8px\] {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[12px\] {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.font-semibold {
|
.font-semibold {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
@ -707,6 +1081,46 @@ video {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-extrabold {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-medium {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.normal-case {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-\[34px\] {
|
||||||
|
line-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-5 {
|
||||||
|
line-height: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-4 {
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-\[0\.18em\] {
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-wide {
|
||||||
|
letter-spacing: 0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-normal {
|
||||||
|
letter-spacing: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
.text-secondary {
|
.text-secondary {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(var(--secondary-text) / var(--tw-text-opacity));
|
color: rgb(var(--secondary-text) / var(--tw-text-opacity));
|
||||||
|
|
@ -717,6 +1131,41 @@ video {
|
||||||
color: rgb(var(--primary-text) / var(--tw-text-opacity));
|
color: rgb(var(--primary-text) / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-email-text {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(244 247 250 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-neon {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(76 227 90 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-muted {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(160 172 184 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-dim {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(112 128 145 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-red {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(240 82 82 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-yellow {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(251 191 36 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-email-purple {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(139 92 246 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.line-through {
|
.line-through {
|
||||||
text-decoration-line: line-through;
|
text-decoration-line: line-through;
|
||||||
}
|
}
|
||||||
|
|
@ -725,6 +1174,11 @@ video {
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.backdrop-filter {
|
||||||
|
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
||||||
|
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
||||||
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/*
|
/*
|
||||||
--primary: #3d3d3d;
|
--primary: #3d3d3d;
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,30 @@ public abstract class CommonDbContext : DbContext
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T Create<T, TParent>(TParent parentI, string navigationName, Action<T> config = null, params object[] constructorArguments) where T : class, new() where TParent : class
|
||||||
|
{
|
||||||
|
var candidates = Model
|
||||||
|
.GetEntityTypes()
|
||||||
|
.Where(x => x.ClrType == typeof(TParent))
|
||||||
|
.FirstOrDefault();
|
||||||
|
var entityT = candidates?.FindNavigation(navigationName)?.TargetEntityType;
|
||||||
|
|
||||||
|
if (entityT == null || entityT.IsOwned())
|
||||||
|
{
|
||||||
|
var childEntity = new T();
|
||||||
|
|
||||||
|
config?.Invoke(childEntity);
|
||||||
|
|
||||||
|
return childEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = this.Set<T>(entityT.Name).CreateProxy(constructorArguments);
|
||||||
|
|
||||||
|
config?.Invoke(entity);
|
||||||
|
this.Add(entity);
|
||||||
|
this.ChangeTracker.DetectChanges();
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
public T Create<T>(Action<T> config = null, params object[] constructorArguments)
|
public T Create<T>(Action<T> config = null, params object[] constructorArguments)
|
||||||
{
|
{
|
||||||
var entity = this.CreateProxy<T>(constructorArguments);
|
var entity = this.CreateProxy<T>(constructorArguments);
|
||||||
|
|
|
||||||
21
Utils/AutoMapPropertyUtils.cs
Normal file
21
Utils/AutoMapPropertyUtils.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Internal;
|
||||||
|
using NejAccountingAPI.Models;
|
||||||
|
|
||||||
|
namespace AutoMapProperty;
|
||||||
|
|
||||||
|
public class AutoMapPropertyUtils
|
||||||
|
{
|
||||||
|
public static T Create<T>(IServiceProvider provider) where T : class
|
||||||
|
{
|
||||||
|
var appDb = provider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
return appDb.Create<T>();
|
||||||
|
}
|
||||||
|
public static T Create<T, TParent>(IServiceProvider provider, TParent parent, string name) where T : class, new() where TParent : class
|
||||||
|
{
|
||||||
|
var appDb = provider.GetRequiredService<AppDbContext>();
|
||||||
|
|
||||||
|
return appDb.Create<T, TParent>(parent, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
412
Utils/RoundingNumericTypeInfoResolverFactory.cs
Normal file
412
Utils/RoundingNumericTypeInfoResolverFactory.cs
Normal file
|
|
@ -0,0 +1,412 @@
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
using Npgsql.Internal;
|
||||||
|
using Npgsql.Internal.Converters;
|
||||||
|
using Npgsql.Internal.Postgres;
|
||||||
|
|
||||||
|
namespace NejCommon.Utils;
|
||||||
|
|
||||||
|
#pragma warning disable NPG9001 // decimalype is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||||
|
public sealed class RoundingNumericTypeInfoResolverFactory
|
||||||
|
: PgTypeInfoResolverFactory
|
||||||
|
{
|
||||||
|
public override IPgTypeInfoResolver CreateResolver()
|
||||||
|
=> new Resolver();
|
||||||
|
|
||||||
|
public override IPgTypeInfoResolver? CreateArrayResolver()
|
||||||
|
=> null;
|
||||||
|
|
||||||
|
private sealed class Resolver : IPgTypeInfoResolver
|
||||||
|
{
|
||||||
|
private readonly TypeInfoMappingCollection _mappings =
|
||||||
|
CreateMappings();
|
||||||
|
|
||||||
|
public PgTypeInfo? GetTypeInfo(
|
||||||
|
Type? type,
|
||||||
|
DataTypeName? dataTypeName,
|
||||||
|
PgSerializerOptions options)
|
||||||
|
=> _mappings.Find(type, dataTypeName, options);
|
||||||
|
|
||||||
|
private static TypeInfoMappingCollection CreateMappings()
|
||||||
|
{
|
||||||
|
var mappings = new TypeInfoMappingCollection();
|
||||||
|
|
||||||
|
mappings.AddStructType<decimal>(
|
||||||
|
"numeric",
|
||||||
|
static (options, mapping, _) =>
|
||||||
|
mapping.CreateInfo(
|
||||||
|
options,
|
||||||
|
new RoundingDecimalNumericConverter()),
|
||||||
|
isDefault: true);
|
||||||
|
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class RoundingDecimalNumericConverter
|
||||||
|
: PgBufferedConverter<decimal>
|
||||||
|
{
|
||||||
|
private const ushort SignPositive = 0x0000;
|
||||||
|
private const ushort SignNegative = 0x4000;
|
||||||
|
private const ushort SignNaN = 0xC000;
|
||||||
|
private const ushort SignPositiveInfinity = 0xD000;
|
||||||
|
private const ushort SignNegativeInfinity = 0xF000;
|
||||||
|
|
||||||
|
private static readonly BigInteger MaxDecimalCoefficient =
|
||||||
|
(BigInteger.One << 96) - 1;
|
||||||
|
|
||||||
|
public override bool CanConvert(
|
||||||
|
DataFormat format,
|
||||||
|
out BufferRequirements bufferRequirements)
|
||||||
|
{
|
||||||
|
// Let Npgsql buffer the entire binary numeric value before calling
|
||||||
|
// ReadCore/WriteCore.
|
||||||
|
return CanConvertBufferedDefault(format, out bufferRequirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override decimal ReadCore(PgReader reader)
|
||||||
|
{
|
||||||
|
// PostgreSQL numeric binary format:
|
||||||
|
//
|
||||||
|
// int16 ndigits
|
||||||
|
// int16 weight
|
||||||
|
// int16 sign
|
||||||
|
// int16 dscale
|
||||||
|
// int16 digits[ndigits]
|
||||||
|
//
|
||||||
|
// Each digit is base 10000.
|
||||||
|
|
||||||
|
var digitCount = reader.ReadInt16();
|
||||||
|
var weight = reader.ReadInt16();
|
||||||
|
var sign = reader.ReadUInt16();
|
||||||
|
|
||||||
|
// IMPORTANT:
|
||||||
|
// This is DISPLAY scale, not necessarily the number of physically
|
||||||
|
// significant fractional digits.
|
||||||
|
//
|
||||||
|
// e.g. 100.000000000000000000000000000000 may have
|
||||||
|
// dscale=30 but physically contain only the digit 100.
|
||||||
|
_ = reader.ReadInt16();
|
||||||
|
|
||||||
|
if (digitCount < 0)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Invalid PostgreSQL numeric digit count: {digitCount}");
|
||||||
|
|
||||||
|
switch (sign)
|
||||||
|
{
|
||||||
|
case SignNaN:
|
||||||
|
throw new InvalidCastException(
|
||||||
|
"Numeric NaN cannot be represented as System.Decimal.");
|
||||||
|
|
||||||
|
case SignPositiveInfinity:
|
||||||
|
throw new InvalidCastException(
|
||||||
|
"Numeric Infinity cannot be represented as System.Decimal.");
|
||||||
|
|
||||||
|
case SignNegativeInfinity:
|
||||||
|
throw new InvalidCastException(
|
||||||
|
"Numeric -Infinity cannot be represented as System.Decimal.");
|
||||||
|
|
||||||
|
case not (SignPositive or SignNegative):
|
||||||
|
throw new InvalidCastException(
|
||||||
|
$"Unknown PostgreSQL numeric sign 0x{sign:X4}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digitCount == 0)
|
||||||
|
return decimal.Zero;
|
||||||
|
|
||||||
|
BigInteger coefficient = BigInteger.Zero;
|
||||||
|
|
||||||
|
for (var i = 0; i < digitCount; i++)
|
||||||
|
{
|
||||||
|
var digit = reader.ReadInt16();
|
||||||
|
|
||||||
|
if (digit is < 0 or >= 10000)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Invalid PostgreSQL numeric digit: {digit}");
|
||||||
|
|
||||||
|
coefficient *= 10000;
|
||||||
|
coefficient += digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ToDecimal(
|
||||||
|
coefficient,
|
||||||
|
digitCount,
|
||||||
|
weight,
|
||||||
|
sign == SignNegative);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static decimal ToDecimal(
|
||||||
|
BigInteger coefficient,
|
||||||
|
int digitCount,
|
||||||
|
int weight,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
if (coefficient.IsZero)
|
||||||
|
return decimal.Zero;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PostgreSQL numeric:
|
||||||
|
*
|
||||||
|
* digits are base 10000
|
||||||
|
* weight tells us the weight of the first group
|
||||||
|
*
|
||||||
|
* Therefore:
|
||||||
|
*
|
||||||
|
* coefficient * 10^(-physicalScale)
|
||||||
|
*
|
||||||
|
* gives us the actual numerical value.
|
||||||
|
*/
|
||||||
|
var physicalScale =
|
||||||
|
checked(4 * (digitCount - 1 - weight));
|
||||||
|
|
||||||
|
// Value has zeroes to the right, e.g. a positive exponent.
|
||||||
|
if (physicalScale < 0)
|
||||||
|
{
|
||||||
|
coefficient *= BigInteger.Pow(10, -physicalScale);
|
||||||
|
physicalScale = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip REAL trailing zeroes first.
|
||||||
|
*
|
||||||
|
* This is the important part for values such as:
|
||||||
|
*
|
||||||
|
* 100.000000000000000000000000000000
|
||||||
|
*
|
||||||
|
* We care about the value, not PostgreSQL's nominal dscale.
|
||||||
|
*/
|
||||||
|
while (physicalScale > 0 &&
|
||||||
|
coefficient % 10 == 0)
|
||||||
|
{
|
||||||
|
coefficient /= 10;
|
||||||
|
physicalScale--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System.Decimal is:
|
||||||
|
*
|
||||||
|
* 96-bit unsigned coefficient
|
||||||
|
* scale 0..28
|
||||||
|
*
|
||||||
|
* Try the highest scale we can preserve.
|
||||||
|
*
|
||||||
|
* If necessary, progressively round away fractional precision.
|
||||||
|
*/
|
||||||
|
var targetScale = Math.Min(physicalScale, 28);
|
||||||
|
|
||||||
|
for (; targetScale >= 0; targetScale--)
|
||||||
|
{
|
||||||
|
var digitsToDrop = physicalScale - targetScale;
|
||||||
|
|
||||||
|
var rounded = digitsToDrop == 0
|
||||||
|
? coefficient
|
||||||
|
: RoundToEven(coefficient, digitsToDrop);
|
||||||
|
|
||||||
|
if (rounded <= MaxDecimalCoefficient)
|
||||||
|
{
|
||||||
|
return CreateDecimal(
|
||||||
|
rounded,
|
||||||
|
targetScale,
|
||||||
|
negative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even integer-scale representation doesn't fit.
|
||||||
|
// This is a REAL overflow rather than useless fractional precision.
|
||||||
|
throw new OverflowException(
|
||||||
|
"PostgreSQL numeric magnitude does not fit in System.Decimal.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigInteger RoundToEven(
|
||||||
|
BigInteger value,
|
||||||
|
int decimalDigitsToDrop)
|
||||||
|
{
|
||||||
|
if (decimalDigitsToDrop <= 0)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
var divisor =
|
||||||
|
BigInteger.Pow(10, decimalDigitsToDrop);
|
||||||
|
|
||||||
|
var quotient =
|
||||||
|
BigInteger.DivRem(value, divisor, out var remainder);
|
||||||
|
|
||||||
|
var doubledRemainder = remainder * 2;
|
||||||
|
var comparison = doubledRemainder.CompareTo(divisor);
|
||||||
|
|
||||||
|
// MidpointRounding.ToEven
|
||||||
|
if (comparison > 0 ||
|
||||||
|
(comparison == 0 && !quotient.IsEven))
|
||||||
|
{
|
||||||
|
quotient++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static decimal CreateDecimal(
|
||||||
|
BigInteger coefficient,
|
||||||
|
int scale,
|
||||||
|
bool negative)
|
||||||
|
{
|
||||||
|
var lo = (uint)(coefficient & uint.MaxValue);
|
||||||
|
var mid = (uint)((coefficient >> 32) & uint.MaxValue);
|
||||||
|
var hi = (uint)((coefficient >> 64) & uint.MaxValue);
|
||||||
|
|
||||||
|
return new decimal(
|
||||||
|
unchecked((int)lo),
|
||||||
|
unchecked((int)mid),
|
||||||
|
unchecked((int)hi),
|
||||||
|
negative,
|
||||||
|
checked((byte)scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------
|
||||||
|
// Writing CLR decimal -> numeric
|
||||||
|
// ----------------------------
|
||||||
|
|
||||||
|
public override Size GetSize(
|
||||||
|
SizeContext context,
|
||||||
|
decimal value,
|
||||||
|
ref object? writeState)
|
||||||
|
{
|
||||||
|
var encoded = Encode(value);
|
||||||
|
|
||||||
|
// ndigits + weight + sign + dscale = 8 bytes
|
||||||
|
// plus 2 bytes per base-10000 digit.
|
||||||
|
return 8 + encoded.Digits.Length * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void WriteCore(
|
||||||
|
PgWriter writer,
|
||||||
|
decimal value)
|
||||||
|
{
|
||||||
|
var encoded = Encode(value);
|
||||||
|
|
||||||
|
writer.WriteInt16(
|
||||||
|
checked((short)encoded.Digits.Length));
|
||||||
|
|
||||||
|
writer.WriteInt16(encoded.Weight);
|
||||||
|
writer.WriteUInt16(encoded.Sign);
|
||||||
|
writer.WriteInt16(encoded.Scale);
|
||||||
|
|
||||||
|
foreach (var digit in encoded.Digits)
|
||||||
|
writer.WriteInt16(digit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EncodedNumeric Encode(decimal value)
|
||||||
|
{
|
||||||
|
var bits = decimal.GetBits(value);
|
||||||
|
|
||||||
|
var negative =
|
||||||
|
(bits[3] & int.MinValue) != 0;
|
||||||
|
|
||||||
|
var scale =
|
||||||
|
(bits[3] >> 16) & 0xFF;
|
||||||
|
|
||||||
|
var coefficient =
|
||||||
|
((BigInteger)(uint)bits[2] << 64) |
|
||||||
|
((BigInteger)(uint)bits[1] << 32) |
|
||||||
|
(uint)bits[0];
|
||||||
|
|
||||||
|
if (coefficient.IsZero)
|
||||||
|
{
|
||||||
|
return new EncodedNumeric(
|
||||||
|
Array.Empty<short>(),
|
||||||
|
0,
|
||||||
|
SignPositive,
|
||||||
|
checked((short)scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
var text =
|
||||||
|
coefficient.ToString(
|
||||||
|
CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
string integerPart;
|
||||||
|
string fractionalPart;
|
||||||
|
|
||||||
|
if (scale == 0)
|
||||||
|
{
|
||||||
|
integerPart = text;
|
||||||
|
fractionalPart = "";
|
||||||
|
}
|
||||||
|
else if (text.Length <= scale)
|
||||||
|
{
|
||||||
|
integerPart = "0";
|
||||||
|
fractionalPart =
|
||||||
|
new string('0', scale - text.Length) + text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
integerPart = text[..^scale];
|
||||||
|
fractionalPart = text[^scale..];
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostgreSQL numeric groups contain 4 decimal digits each.
|
||||||
|
var integerPadding =
|
||||||
|
(4 - integerPart.Length % 4) % 4;
|
||||||
|
|
||||||
|
integerPart =
|
||||||
|
new string('0', integerPadding) +
|
||||||
|
integerPart;
|
||||||
|
|
||||||
|
var fractionalPadding =
|
||||||
|
(4 - fractionalPart.Length % 4) % 4;
|
||||||
|
|
||||||
|
fractionalPart +=
|
||||||
|
new string('0', fractionalPadding);
|
||||||
|
|
||||||
|
var integerGroups =
|
||||||
|
integerPart.Length / 4;
|
||||||
|
|
||||||
|
var all = integerPart + fractionalPart;
|
||||||
|
|
||||||
|
var groups =
|
||||||
|
new List<short>(all.Length / 4);
|
||||||
|
|
||||||
|
for (var i = 0; i < all.Length; i += 4)
|
||||||
|
{
|
||||||
|
groups.Add(
|
||||||
|
short.Parse(
|
||||||
|
all.AsSpan(i, 4),
|
||||||
|
CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
var weight = integerGroups - 1;
|
||||||
|
|
||||||
|
// PostgreSQL itself doesn't transmit unnecessary leading groups.
|
||||||
|
while (groups.Count > 0 && groups[0] == 0)
|
||||||
|
{
|
||||||
|
groups.RemoveAt(0);
|
||||||
|
weight--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nor unnecessary trailing groups.
|
||||||
|
while (groups.Count > 0 &&
|
||||||
|
groups[^1] == 0)
|
||||||
|
{
|
||||||
|
groups.RemoveAt(groups.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groups.Count == 0)
|
||||||
|
weight = 0;
|
||||||
|
|
||||||
|
return new EncodedNumeric(
|
||||||
|
groups.ToArray(),
|
||||||
|
checked((short)weight),
|
||||||
|
negative
|
||||||
|
? SignNegative
|
||||||
|
: SignPositive,
|
||||||
|
checked((short)scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record EncodedNumeric(
|
||||||
|
short[] Digits,
|
||||||
|
short Weight,
|
||||||
|
ushort Sign,
|
||||||
|
short Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning restore NPG9001 // decimalype is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||||
Loading…
Reference in New Issue
Block a user