From f647120cd12f10a23410cdd1cff5cbd9b7a46035 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 6 Apr 2021 18:17:09 +0200 Subject: [PATCH 001/300] initial showcase implementation --- .../InvenTree/static/script/chart.min.js | 13 ++++ InvenTree/order/models.py | 5 +- InvenTree/order/views.py | 1 + .../part/templates/part/part_pricing.html | 71 +++++++++++++++++++ InvenTree/part/views.py | 24 +++++++ InvenTree/templates/base.html | 1 + 6 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 InvenTree/InvenTree/static/script/chart.min.js diff --git a/InvenTree/InvenTree/static/script/chart.min.js b/InvenTree/InvenTree/static/script/chart.min.js new file mode 100644 index 0000000000..fb766197fc --- /dev/null +++ b/InvenTree/InvenTree/static/script/chart.min.js @@ -0,0 +1,13 @@ +/*! + * Chart.js v3.0.2 + * https://www.chartjs.org + * (c) 2021 Chart.js Contributors + * Released under the MIT License + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";const t="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function e(e,i,n){const o=n||(t=>Array.prototype.slice.call(t));let s=!1,a=[];return function(...n){a=o(n),s||(s=!0,t.call(window,(()=>{s=!1,e.apply(i,a)})))}}function i(t,e){let i;return function(){return e?(clearTimeout(i),i=setTimeout(t,e)):t(),e}}const n=t=>"start"===t?"left":"end"===t?"right":"center",o=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,s=(t,e,i)=>"right"===t?i:"center"===t?(e+i)/2:e;var a=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,n){const o=e.listeners[n],s=e.duration;o.forEach((n=>n({chart:t,numSteps:s,currentStep:Math.min(i-e.start,s)})))}_refresh(){const e=this;e._request||(e._running=!0,e._request=t.call(window,(()=>{e._update(),e._request=null,e._running&&e._refresh()})))}_update(t=Date.now()){const e=this;let i=0;e._charts.forEach(((n,o)=>{if(!n.running||!n.items.length)return;const s=n.items;let a,r=s.length-1,l=!1;for(;r>=0;--r)a=s[r],a._active?(a._total>n.duration&&(n.duration=a._total),a.tick(t),l=!0):(s[r]=s[s.length-1],s.pop());l&&(o.draw(),e._notify(o,n,t,"progress")),s.length||(n.running=!1,e._notify(o,n,t,"complete")),i+=s.length})),e._lastDate=t,0===i&&(e._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let n=i.length-1;for(;n>=0;--n)i[n].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}}; +/*! + * @kurkle/color v0.1.9 + * https://github.com/kurkle/color#readme + * (c) 2020 Jukka Kurkela + * Released under the MIT License + */const r={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},l="0123456789ABCDEF",c=t=>l[15&t],h=t=>l[(240&t)>>4]+l[15&t],d=t=>(240&t)>>4==(15&t);function u(t){var e=function(t){return d(t.r)&&d(t.g)&&d(t.b)&&d(t.a)}(t)?c:h;return t?"#"+e(t.r)+e(t.g)+e(t.b)+(t.a<255?e(t.a):""):t}function f(t){return t+.5|0}const g=(t,e,i)=>Math.max(Math.min(t,i),e);function p(t){return g(f(2.55*t),0,255)}function m(t){return g(f(255*t),0,255)}function x(t){return g(f(t/2.55)/100,0,1)}function b(t){return g(f(100*t),0,100)}const _=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const y=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function v(t,e,i){const n=e*Math.min(i,1-i),o=(e,o=(e+t/30)%12)=>i-n*Math.max(Math.min(o-3,9-o,1),-1);return[o(0),o(8),o(4)]}function M(t,e,i){const n=(n,o=(n+t/60)%6)=>i-i*e*Math.max(Math.min(o,4-o,1),0);return[n(5),n(3),n(1)]}function w(t,e,i){const n=v(t,1,.5);let o;for(e+i>1&&(o=1/(e+i),e*=o,i*=o),o=0;o<3;o++)n[o]*=1-e-i,n[o]+=e;return n}function k(t){const e=t.r/255,i=t.g/255,n=t.b/255,o=Math.max(e,i,n),s=Math.min(e,i,n),a=(o+s)/2;let r,l,c;return o!==s&&(c=o-s,l=a>.5?c/(2-o-s):c/(o+s),r=o===e?(i-n)/c+(i>16&255,s>>8&255,255&s]}return t}(),T.transparent=[0,0,0,0]);const e=T[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}function R(t,e,i){if(t){let n=k(t);n[e]=Math.max(0,Math.min(n[e]+n[e]*i,0===e?360:1)),n=P(n),t.r=n[0],t.g=n[1],t.b=n[2]}}function E(t,e){return t?Object.assign(e||{},t):t}function I(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=m(t[3]))):(e=E(t,{r:0,g:0,b:0,a:1})).a=m(e.a),e}function F(t){return"r"===t.charAt(0)?function(t){const e=_.exec(t);let i,n,o,s=255;if(e){if(e[7]!==i){const t=+e[7];s=255&(e[8]?p(t):255*t)}return i=+e[1],n=+e[3],o=+e[5],i=255&(e[2]?p(i):i),n=255&(e[4]?p(n):n),o=255&(e[6]?p(o):o),{r:i,g:n,b:o,a:s}}}(t):C(t)}class z{constructor(t){if(t instanceof z)return t;const e=typeof t;let i;var n,o,s;"object"===e?i=I(t):"string"===e&&(s=(n=t).length,"#"===n[0]&&(4===s||5===s?o={r:255&17*r[n[1]],g:255&17*r[n[2]],b:255&17*r[n[3]],a:5===s?17*r[n[4]]:255}:7!==s&&9!==s||(o={r:r[n[1]]<<4|r[n[2]],g:r[n[3]]<<4|r[n[4]],b:r[n[5]]<<4|r[n[6]],a:9===s?r[n[7]]<<4|r[n[8]]:255})),i=o||L(t)||F(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=E(this._rgb);return t&&(t.a=x(t.a)),t}set rgb(t){this._rgb=I(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${x(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):this._rgb;var t}hexString(){return this._valid?u(this._rgb):this._rgb}hslString(){return this._valid?function(t){if(!t)return;const e=k(t),i=e[0],n=b(e[1]),o=b(e[2]);return t.a<255?`hsla(${i}, ${n}%, ${o}%, ${x(t.a)})`:`hsl(${i}, ${n}%, ${o}%)`}(this._rgb):this._rgb}mix(t,e){const i=this;if(t){const n=i.rgb,o=t.rgb;let s;const a=e===s?.5:e,r=2*a-1,l=n.a-o.a,c=((r*l==-1?r:(r+l)/(1+r*l))+1)/2;s=1-c,n.r=255&c*n.r+s*o.r+.5,n.g=255&c*n.g+s*o.g+.5,n.b=255&c*n.b+s*o.b+.5,n.a=a*n.a+(1-a)*o.a,i.rgb=n}return i}clone(){return new z(this.rgb)}alpha(t){return this._rgb.a=m(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=f(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return R(this._rgb,2,t),this}darken(t){return R(this._rgb,2,-t),this}saturate(t){return R(this._rgb,1,t),this}desaturate(t){return R(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=k(t);i[0]=D(i[0]+e),i=P(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function V(t){return new z(t)}const B=t=>t instanceof CanvasGradient||t instanceof CanvasPattern;function W(t){return B(t)?t:V(t)}function H(t){return B(t)?t:V(t).saturate(.5).darken(.1).hexString()}function N(){}const j=function(){let t=0;return function(){return t++}}();function $(t){return null==t}function Y(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)}function U(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const X=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function q(t,e){return X(t)?t:e}function K(t,e){return void 0===t?e:t}const G=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,Z=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function Q(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function J(t,e,i,n){let o,s,a;if(Y(t))if(s=t.length,n)for(o=s-1;o>=0;o--)e.call(i,t[o],o);else for(o=0;oi;)t=t[e.substr(i,n-i)],i=n+1,n=rt(e,i);return t}function ct(t){return t.charAt(0).toUpperCase()+t.slice(1)}const ht=t=>void 0!==t,dt=t=>"function"==typeof t,ut=Object.create(null),ft=Object.create(null);function gt(t,e){if(!e)return t;const i=e.split(".");for(let e=0,n=i.length;et.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>H(e.backgroundColor),this.hoverBorderColor=(t,e)=>H(e.borderColor),this.hoverColor=(t,e)=>H(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.describe(t)}set(t,e){return pt(this,t,e)}get(t){return gt(this,t)}describe(t,e){return pt(ft,t,e)}override(t,e){return pt(ut,t,e)}route(t,e,i,n){const o=gt(this,t),s=gt(this,i),a="_"+e;Object.defineProperties(o,{[a]:{value:o[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[a],e=s[n];return U(t)?Object.assign({},e,t):K(t,e)},set(t){this[a]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});const xt=Math.PI,bt=2*xt,_t=bt+xt,yt=Number.POSITIVE_INFINITY,vt=xt/180,Mt=xt/2,wt=xt/4,kt=2*xt/3,St=Math.log10,Pt=Math.sign;function Dt(t){const e=Math.pow(10,Math.floor(St(t))),i=t/e;return(i<=1?1:i<=2?2:i<=5?5:10)*e}function Ct(t){const e=[],i=Math.sqrt(t);let n;for(n=1;nt-e)).pop(),e}function At(t){return!isNaN(parseFloat(t))&&isFinite(t)}function Ot(t,e,i){return Math.abs(t-e)=t}function Lt(t,e,i){let n,o,s;for(n=0,o=t.length;nr&&ln&&(n=s),n}function Yt(t,e,i,n){let o=(n=n||{}).data=n.data||{},s=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(o=n.data={},s=n.garbageCollect=[],n.font=e),t.save(),t.font=e;let a=0;const r=i.length;let l,c,h,d,u;for(l=0;li.length){for(l=0;l0&&t.stroke()}}function Kt(t,e,i){return i=i||.5,t&&t.x>e.left-i&&t.xe.top-i&&t.y0&&""!==s.strokeColor;let l,c;for(t.save(),s.translation&&t.translate(s.translation[0],s.translation[1]),$(s.rotation)||t.rotate(s.rotation),t.font=o.string,s.color&&(t.fillStyle=s.color),s.textAlign&&(t.textAlign=s.textAlign),s.textBaseline&&(t.textBaseline=s.textBaseline),l=0;lt[i]1;)n=s+o>>1,i(n)?s=n:o=n;return{lo:s,hi:o}}const ie=(t,e,i)=>ee(t,i,(n=>t[n][e]ee(t,i,(n=>t[n][e]>=i));function oe(t,e,i){let n=0,o=t.length;for(;nn&&t[o-1]>i;)o--;return n>0||o{const i="_onData"+ct(e),n=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const o=n.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),o}})})))}function re(t,e){const i=t._chartjs;if(!i)return;const n=i.listeners,o=n.indexOf(e);-1!==o&&n.splice(o,1),n.length>0||(se.forEach((e=>{delete t[e]})),delete t._chartjs)}function le(t){const e=new Set;let i,n;for(i=0,n=t.length;i{o.push(t)})),o}function ce(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function he(t,e,i){let n;return"string"==typeof t?(n=parseInt(t,10),-1!==t.indexOf("%")&&(n=n/100*e.parentNode[i])):n=t,n}const de=t=>window.getComputedStyle(t,null);function ue(t,e){return de(t).getPropertyValue(e)}const fe=["top","right","bottom","left"];function ge(t,e,i){const n={};i=i?"-"+i:"";for(let o=0;o<4;o++){const s=fe[o];n[s]=parseFloat(t[e+"-"+s+i])||0}return n.width=n.left+n.right,n.height=n.top+n.bottom,n}function pe(t,e){const{canvas:i,currentDevicePixelRatio:n}=e,o=de(i),s="border-box"===o.boxSizing,a=ge(o,"padding"),r=ge(o,"border","width"),{x:l,y:c,box:h}=function(t,e){const i=t.native||t,n=i.touches,o=n&&n.length?n[0]:i,{offsetX:s,offsetY:a}=o;let r,l,c=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(s,a,i.target))r=s,l=a;else{const t=e.getBoundingClientRect();r=o.clientX-t.left,l=o.clientY-t.top,c=!0}return{x:r,y:l,box:c}}(t,i),d=a.left+(h&&r.left),u=a.top+(h&&r.top);let{width:f,height:g}=e;return s&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/n),y:Math.round((c-u)/g*i.height/n)}}const me=t=>Math.round(10*t)/10;function xe(t,e,i,n){const o=de(t),s=ge(o,"margin"),a=he(o.maxWidth,t,"clientWidth")||yt,r=he(o.maxHeight,t,"clientHeight")||yt,l=function(t,e,i){let n,o;if(void 0===e||void 0===i){const s=ce(t);if(s){const t=s.getBoundingClientRect(),a=de(s),r=ge(a,"border","width"),l=ge(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,n=he(a.maxWidth,s,"clientWidth"),o=he(a.maxHeight,s,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:n||yt,maxHeight:o||yt}}(t,e,i);let{width:c,height:h}=l;if("content-box"===o.boxSizing){const t=ge(o,"border","width"),e=ge(o,"padding");c-=e.width+t.width,h-=e.height+t.height}return c=Math.max(0,c-s.width),h=Math.max(0,n?Math.floor(c/n):h-s.height),c=me(Math.min(c,a,l.maxWidth)),h=me(Math.min(h,r,l.maxHeight)),c&&!h&&(h=me(c/2)),{width:c,height:h}}function be(t,e,i){const n=t.currentDevicePixelRatio=e||1,{canvas:o,width:s,height:a}=t;o.height=a*n,o.width=s*n,t.ctx.setTransform(n,0,0,n,0,0),o.style&&(i||!o.style.height&&!o.style.width)&&(o.style.height=a+"px",o.style.width=s+"px")}const _e=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function ye(t,e){const i=ue(t,e),n=i&&i.match(/^(\d+)(\.\d+)?px$/);return n?+n[1]:void 0}function ve(t,e){return"native"in t?{x:t.x,y:t.y}:pe(t,e)}function Me(t,e,i,n){const{controller:o,data:s,_sorted:a}=t,r=o._cachedMeta.iScale;if(r&&e===r.axis&&a&&s.length){const t=r._reversePixels?ne:ie;if(!n)return t(s,e,i);if(o._sharedOptions){const n=s[0],o="function"==typeof n.getRange&&n.getRange(e);if(o){const n=t(s,e,i-o),a=t(s,e,i+o);return{lo:n.lo,hi:a.hi}}}}return{lo:0,hi:s.length-1}}function we(t,e,i,n,o){const s=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=s.length;t{t[r](o[a],n)&&s.push({element:t,datasetIndex:e,index:i}),t.inRange(o.x,o.y,n)&&(l=!0)})),i.intersect&&!l?[]:s}var De={modes:{index(t,e,i,n){const o=ve(e,t),s=i.axis||"x",a=i.intersect?ke(t,o,s,n):Se(t,o,s,!1,n),r=[];return a.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=a[0].index,i=t.data[e];i&&!i.skip&&r.push({element:i,datasetIndex:t.index,index:e})})),r):[]},dataset(t,e,i,n){const o=ve(e,t),s=i.axis||"xy";let a=i.intersect?ke(t,o,s,n):Se(t,o,s,!1,n);if(a.length>0){const e=a[0].datasetIndex,i=t.getDatasetMeta(e).data;a=[];for(let t=0;tke(t,ve(e,t),i.axis||"xy",n),nearest:(t,e,i,n)=>Se(t,ve(e,t),i.axis||"xy",i.intersect,n),x:(t,e,i,n)=>(i.axis="x",Pe(t,e,i,n)),y:(t,e,i,n)=>(i.axis="y",Pe(t,e,i,n))}};const Ce=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);function Ae(t,e){const i=(""+t).match(Ce);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function Oe(t,e){const i={},n=U(e),o=n?Object.keys(e):e,s=U(t)?n?i=>K(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of o)i[t]=+s(t)||0;return i}function Te(t){return Oe(t,{top:"y",right:"x",bottom:"y",left:"x"})}function Le(t){return Oe(t,["topLeft","topRight","bottomLeft","bottomRight"])}function Re(t){const e=Te(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function Ee(t,e){t=t||{},e=e||mt.font;let i=K(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));const n={family:K(t.family,e.family),lineHeight:Ae(K(t.lineHeight,e.lineHeight),i),size:i,style:K(t.style,e.style),weight:K(t.weight,e.weight),string:""};return n.string=jt(n),n}function Ie(t,e,i,n){let o,s,a,r=!0;for(o=0,s=t.length;ot.pos===e))}function Be(t,e){return t.filter((t=>-1===ze.indexOf(t.pos)&&t.box.axis===e))}function We(t,e){return t.sort(((t,i)=>{const n=e?i:t,o=e?t:i;return n.weight===o.weight?n.index-o.index:n.weight-o.weight}))}function He(t,e,i,n){return Math.max(t[i],e[i])+Math.max(t[n],e[n])}function Ne(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function je(t,e,i){const n=i.box,o=t.maxPadding;if(U(i.pos))return{same:!1,other:!1};i.size&&(t[i.pos]-=i.size),i.size=i.horizontal?n.height:n.width,t[i.pos]+=i.size,n.getPadding&&Ne(o,n.getPadding());const s=Math.max(0,e.outerWidth-He(o,t,"left","right")),a=Math.max(0,e.outerHeight-He(o,t,"top","bottom")),r=s!==t.w,l=a!==t.h;return t.w=s,t.h=a,i.horizontal?{same:r,other:l}:{same:l,other:r}}function $e(t,e){const i=e.maxPadding;function n(t){const n={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{n[t]=Math.max(e[t],i[t])})),n}return n(t?["left","right"]:["top","bottom"])}function Ye(t,e,i){const n=[];let o,s,a,r,l,c;for(o=0,s=t.length,l=0;ot.box.fullSize)),!0),n=We(Ve(e,"left"),!0),o=We(Ve(e,"right")),s=We(Ve(e,"top"),!0),a=We(Ve(e,"bottom")),r=Be(e,"x"),l=Be(e,"y");return{fullSize:i,leftAndTop:n.concat(s),rightAndBottom:o.concat(l).concat(a).concat(r),chartArea:Ve(e,"chartArea"),vertical:n.concat(o).concat(l),horizontal:s.concat(a).concat(r)}}(t.boxes),l=r.vertical,c=r.horizontal;J(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const h=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:o,availableWidth:s,availableHeight:a,vBoxMaxWidth:s/2/h,hBoxMaxHeight:a/2}),u=Object.assign({},o);Ne(u,Re(n));const f=Object.assign({maxPadding:u,w:s,h:a,x:o.left,y:o.top},o);!function(t,e){let i,n,o;for(i=0,n=t.length;i{const i=e.box;Object.assign(i,t.chartArea),i.update(f.w,f.h)}))}};class qe{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,n){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,n?Math.floor(e/n):i)}}isAttached(t){return!0}}class Ke extends qe{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}}const Ge={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},Ze=t=>null===t||""===t;const Qe=!!_e&&{passive:!0};function Je(t,e,i){t.canvas.removeEventListener(e,i,Qe)}function ti(t,e,i){const n=t.canvas,o=n&&ce(n)||n,s=new MutationObserver((t=>{const e=ce(o);t.forEach((t=>{for(let n=0;n{t.forEach((t=>{for(let e=0;e{i.currentDevicePixelRatio!==t&&e()})))}function si(t,i,n){const o=t.canvas,s=o&&ce(o);if(!s)return;const a=e(((t,e)=>{const i=s.clientWidth;n(t,e),i{const e=t[0],i=e.contentRect.width,n=e.contentRect.height;0===i&&0===n||a(i,n)}));return r.observe(s),function(t,e){ii.size||window.addEventListener("resize",oi),ii.set(t,e)}(t,a),r}function ai(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){ii.delete(t),ii.size||window.removeEventListener("resize",oi)}(t)}function ri(t,i,n){const o=t.canvas,s=e((e=>{null!==t.ctx&&n(function(t,e){const i=Ge[t.type]||t.type,{x:n,y:o}=pe(t,e);return{type:i,chart:e,native:t,x:void 0!==n?n:null,y:void 0!==o?o:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,Qe)}(o,i,s),s}class li extends qe{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,n=t.getAttribute("height"),o=t.getAttribute("width");if(t.$chartjs={initial:{height:n,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",Ze(o)){const e=ye(t,"width");void 0!==e&&(t.width=e)}if(Ze(n))if(""===t.style.height)t.height=t.width/(e||2);else{const e=ye(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const i=e.$chartjs.initial;["height","width"].forEach((t=>{const n=i[t];$(n)?e.removeAttribute(t):e.setAttribute(t,n)}));const n=i.style||{};return Object.keys(n).forEach((t=>{e.style[t]=n[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const n=t.$proxies||(t.$proxies={}),o={attach:ti,detach:ei,resize:si}[e]||ri;n[e]=o(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),n=i[e];if(!n)return;({attach:ai,detach:ai,resize:ai}[e]||Je)(t,e,n),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,n){return xe(t,e,i,n)}isAttached(t){const e=ce(t);return!(!e||!ce(e))}}var ci=Object.freeze({__proto__:null,BasePlatform:qe,BasicPlatform:Ke,DomPlatform:li});const hi=t=>0===t||1===t,di=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*bt/i),ui=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*bt/i)+1,fi={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*Mt),easeOutSine:t=>Math.sin(t*Mt),easeInOutSine:t=>-.5*(Math.cos(xt*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>hi(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>hi(t)?t:di(t,.075,.3),easeOutElastic:t=>hi(t)?t:ui(t,.075,.3),easeInOutElastic(t){const e=.1125;return hi(t)?t:t<.5?.5*di(2*t,e,.45):.5+.5*ui(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-fi.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*fi.easeInBounce(2*t):.5*fi.easeOutBounce(2*t-1)+.5},gi="transparent",pi={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const n=W(t||gi),o=n.valid&&W(e||gi);return o&&o.valid?o.mix(n,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class mi{constructor(t,e,i,n){const o=e[i];n=Ie([t.to,n,o,t.from]);const s=Ie([t.from,o,n]);this._active=!0,this._fn=t.fn||pi[t.type||typeof s],this._easing=fi[t.easing]||fi.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=s,this._to=n,this._promises=void 0}active(){return this._active}update(t,e,i){const n=this;if(n._active){n._notify(!1);const o=n._target[n._prop],s=i-n._start,a=n._duration-s;n._start=i,n._duration=Math.floor(Math.max(a,t.duration)),n._total+=s,n._loop=!!t.loop,n._to=Ie([t.to,e,o,t.from]),n._from=Ie([t.from,o,e])}}cancel(){const t=this;t._active&&(t.tick(Date.now()),t._active=!1,t._notify(!1))}tick(t){const e=this,i=t-e._start,n=e._duration,o=e._prop,s=e._from,a=e._loop,r=e._to;let l;if(e._active=s!==r&&(a||i1?2-l:l,l=e._easing(Math.min(1,Math.max(0,l))),e._target[o]=e._fn(s,r,l))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),mt.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),mt.describe("animations",{_fallback:"animation"}),mt.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class bi{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!U(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const n=t[i];if(!U(n))return;const o={};for(const t of xi)o[t]=n[t];(Y(n.properties)&&n.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,o)}))}))}_animateOptions(t,e){const i=e.options,n=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!n)return[];const o=this._createAnimations(n,i);return i.$shared&&function(t,e){const i=[],n=Object.keys(e);for(let e=0;e{t.options=i}),(()=>{})),o}_createAnimations(t,e){const i=this._properties,n=[],o=t.$animations||(t.$animations={}),s=Object.keys(e),a=Date.now();let r;for(r=s.length-1;r>=0;--r){const l=s[r];if("$"===l.charAt(0))continue;if("options"===l){n.push(...this._animateOptions(t,e));continue}const c=e[l];let h=o[l];const d=i.get(l);if(h){if(d&&h.active()){h.update(d,c,a);continue}h.cancel()}d&&d.duration?(o[l]=h=new mi(d,t,l,c),n.push(h)):t[l]=c}return n}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(a.add(this._chart,i),!0):void 0}}function _i(t,e){const i=t&&t.options||{},n=i.reverse,o=void 0===i.min?e:0,s=void 0===i.max?e:0;return{start:n?s:o,end:n?o:s}}function yi(t,e){const i=[],n=t._getSortedDatasetMetas(e);let o,s;for(o=0,s=n.length;oi[t].axis===e)).shift()}function Pi(t,e){e=e||t._parsed;for(const i of e){const e=i._stacks;if(!e||void 0===e[t.vScale.id]||void 0===e[t.vScale.id][t.index])return;delete e[t.vScale.id][t.index]}}const Di=t=>"reset"===t||"none"===t,Ci=(t,e)=>e?t:Object.assign({},t);class Ai{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.$context=void 0,this.initialize()}initialize(){const t=this,e=t._cachedMeta;t.configure(),t.linkScales(),e._stacked=Mi(e.vScale,e),t.addElements()}updateIndex(t){this.index=t}linkScales(){const t=this,e=t.chart,i=t._cachedMeta,n=t.getDataset(),o=(t,e,i,n)=>"x"===t?e:"r"===t?n:i,s=i.xAxisID=K(n.xAxisID,Si(e,"x")),a=i.yAxisID=K(n.yAxisID,Si(e,"y")),r=i.rAxisID=K(n.rAxisID,Si(e,"r")),l=i.indexAxis,c=i.iAxisID=o(l,s,a,r),h=i.vAxisID=o(l,a,s,r);i.xScale=t.getScaleForId(s),i.yScale=t.getScaleForId(a),i.rScale=t.getScaleForId(r),i.iScale=t.getScaleForId(c),i.vScale=t.getScaleForId(h)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&re(this._data,this),t._stacked&&Pi(t)}_dataCheck(){const t=this,e=t.getDataset(),i=e.data||(e.data=[]);U(i)?t._data=function(t){const e=Object.keys(t),i=new Array(e.length);let n,o,s;for(n=0,o=e.length;n0&&n._parsed[t-1];if(!1===i._parsing)n._parsed=o,n._sorted=!0;else{h=Y(o[t])?i.parseArrayData(n,o,t,e):U(o[t])?i.parseObjectData(n,o,t,e):i.parsePrimitiveData(n,o,t,e);const s=()=>null===c[r]||u&&c[r]p||d=0;--u)if(!m()){i.updateRangeFromParsed(c,t,g,l);break}return c}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let n,o,s;for(n=0,o=e.length;n=0&&tn.getContext(i,o)),d);return g.$shared&&(g.$shared=l,s[a]=Object.freeze(Ci(g,l))),g}_resolveAnimations(t,e,i){const n=this,o=n.chart,s=n._cachedDataOpts,a="animation-"+e,r=s[a];if(r)return r;let l;if(!1!==o.options.animation){const o=n.chart.config,s=o.datasetAnimationScopeKeys(n._type,e),a=o.getOptionScopes(n.getDataset(),s);l=o.createResolver(a,n.getContext(t,i,e))}const c=new bi(o,l&&l.animations);return l&&l._cacheable&&(s[a]=Object.freeze(c)),c}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||Di(t)||this.chart._animationsDisabled}updateElement(t,e,i,n){Di(n)?Object.assign(t,i):this._resolveAnimations(e,n).update(t,i)}updateSharedOptions(t,e,i){t&&!Di(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,n){t.active=n;const o=this.getStyle(e,n);this._resolveAnimations(e,i,n).update(t,{options:!n&&this.getSharedOptions(o)||o})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this,i=e._cachedMeta.data.length,n=e._data.length;n>i?e._insertElements(i,n-i,t):n{for(t.length+=e,r=t.length-1;r>=a;r--)t[r]=t[r-e]};for(l(s),r=t;r{o[t]=n[t]&&n[t].active()?n[t]._to:i[t]})),o}}Oi.defaults={},Oi.defaultRoutes=void 0;const Ti=new Map;function Li(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let n=Ti.get(i);return n||(n=new Intl.NumberFormat(t,e),Ti.set(i,n)),n}(e,i).format(t)}const Ri={values:t=>Y(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const n=this.chart.options.locale;let o,s=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(o="scientific"),s=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=St(Math.abs(s)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:o,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),Li(t,n,l)},logarithmic(t,e,i){if(0===t)return"0";const n=t/Math.pow(10,Math.floor(St(t)));return 1===n||2===n||5===n?Ri.numeric.call(this,t,e,i):""}};var Ei={formatters:Ri};function Ii(t,e){const i=t.options.ticks,n=i.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),n=t._length/i+(e?0:1),o=t._maxLength/i;return Math.floor(Math.min(n,o))}(t),o=i.major.enabled?function(t){const e=[];let i,n;for(i=0,n=t.length;in)return function(t,e,i,n){let o,s=0,a=i[0];for(n=Math.ceil(n),o=0;oo)return e}return Math.max(o,1)}(o,e,n);if(s>0){let t,i;const n=s>1?Math.round((r-a)/(s-1)):null;for(Fi(e,l,c,$(n)?0:a-n,a),t=0,i=s-1;te.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderColor:(t,e)=>e.color,borderWidth:(t,e)=>e.lineWidth},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Ei.formatters.values,minor:{},major:{},align:"center",crossAlign:"near"}}),mt.route("scale.ticks","color","","color"),mt.route("scale.grid","color","","borderColor"),mt.route("scale.title","color","","color"),mt.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),mt.describe("scales",{_fallback:"scale"});const zi=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function Vi(t,e){const i=[],n=t.length/e,o=t.length;let s=0;for(;sa+r)))return c}function Wi(t){return t.drawTicks?t.tickLength:0}function Hi(t,e){if(!t.display)return 0;const i=Ee(t.font,e),n=Re(t.padding);return(Y(t.text)?t.text.length:1)*i.lineHeight+n.height}function Ni(t,e,i){let o=n(t);return(i&&"right"!==e||!i&&"right"===e)&&(o=(t=>"left"===t?"right":"right"===t?"left":t)(o)),o}class ji extends Oi{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){const e=this;e.options=t,e.axis=t.axis,e._userMin=e.parse(t.min),e._userMax=e.parse(t.max),e._suggestedMin=e.parse(t.suggestedMin),e._suggestedMax=e.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:n}=this;return t=q(t,Number.POSITIVE_INFINITY),e=q(e,Number.NEGATIVE_INFINITY),i=q(i,Number.POSITIVE_INFINITY),n=q(n,Number.NEGATIVE_INFINITY),{min:q(t,i),max:q(e,n),minDefined:X(t),maxDefined:X(e)}}getMinMax(t){const e=this;let i,{min:n,max:o,minDefined:s,maxDefined:a}=e.getUserBounds();if(s&&a)return{min:n,max:o};const r=e.getMatchingVisibleMetas();for(let l=0,c=r.length;l=s||n<=1||!t.isHorizontal())return void(t.labelRotation=o);const h=t._getLabelSizes(),d=h.widest.width,u=h.highest.height,f=Ht(t.chart.width-d,0,t.maxWidth);a=e.offset?t.maxWidth/n:f/(n-1),d+6>a&&(a=f/(n-(e.offset?.5:1)),r=t.maxHeight-Wi(e.grid)-i.padding-Hi(e.title,t.chart.options.font),l=Math.sqrt(d*d+u*u),c=Et(Math.min(Math.asin(Math.min((h.highest.height+6)/a,1)),Math.asin(Math.min(r/l,1))-Math.asin(u/l))),c=Math.max(o,Math.min(s,c))),t.labelRotation=c}afterCalculateLabelRotation(){Q(this.options.afterCalculateLabelRotation,[this])}beforeFit(){Q(this.options.beforeFit,[this])}fit(){const t=this,e={width:0,height:0},{chart:i,options:{ticks:n,title:o,grid:s}}=t,a=t._isVisible(),r=t.isHorizontal();if(a){const a=Hi(o,i.options.font);if(r?(e.width=t.maxWidth,e.height=Wi(s)+a):(e.height=t.maxHeight,e.width=Wi(s)+a),n.display&&t.ticks.length){const{first:i,last:o,widest:s,highest:a}=t._getLabelSizes(),l=2*n.padding,c=Rt(t.labelRotation),h=Math.cos(c),d=Math.sin(c);if(r){const i=d*s.width+h*a.height;e.height=Math.min(t.maxHeight,e.height+i+l)}else{const i=n.mirror?0:h*s.width+d*a.height;e.width=Math.min(t.maxWidth,e.width+i+l)}t._calculatePadding(i,o,d,h)}}t._handleMargins(),r?(t.width=t._length=i.width-t._margins.left-t._margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=i.height-t._margins.top-t._margins.bottom)}_calculatePadding(t,e,i,n){const o=this,{ticks:{align:s,padding:a},position:r}=o.options,l=0!==o.labelRotation,c="top"!==r&&"x"===o.axis;if(o.isHorizontal()){const r=o.getPixelForTick(0)-o.left,h=o.right-o.getPixelForTick(o.ticks.length-1);let d=0,u=0;l?c?(d=n*t.width,u=i*e.height):(d=i*t.height,u=n*e.width):"start"===s?u=e.width:"end"===s?d=t.width:(d=t.width/2,u=e.width/2),o.paddingLeft=Math.max((d-r+a)*o.width/(o.width-r),0),o.paddingRight=Math.max((u-h+a)*o.width/(o.width-h),0)}else{let i=e.height/2,n=t.height/2;"start"===s?(i=0,n=t.height):"end"===s&&(i=e.height,n=0),o.paddingTop=i+a,o.paddingBottom=n+a}}_handleMargins(){const t=this;t._margins&&(t._margins.left=Math.max(t.paddingLeft,t._margins.left),t._margins.top=Math.max(t.paddingTop,t._margins.top),t._margins.right=Math.max(t.paddingRight,t._margins.right),t._margins.bottom=Math.max(t.paddingBottom,t._margins.bottom))}afterFit(){Q(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){const e=this;e.beforeTickToLabelConversion(),e.generateTickLabels(t),e.afterTickToLabelConversion()}_getLabelSizes(){const t=this;let e=t._labelSizes;if(!e){const i=t.options.ticks.sampleSize;let n=t.ticks;i{const i=t.gc,n=i.length/2;let o;if(n>e){for(o=0;o({width:o[t]||0,height:s[t]||0});return{first:v(0),last:v(e-1),widest:v(_),highest:v(y)}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){const e=this;e._reversePixels&&(t=1-t);const i=e._startPixel+t*e._length;return Nt(e._alignToPixels?Ut(e.chart,i,0):i)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this,i=e.ticks||[];if(t>=0&&tr*o?r/n:l/o:l*o0}_computeGridLineItems(t){const e=this,i=e.axis,n=e.chart,o=e.options,{grid:s,position:a}=o,r=s.offset,l=e.isHorizontal(),c=e.ticks.length+(r?1:0),h=Wi(s),d=[],u=s.setContext(e.getContext(0)),f=u.drawBorder?u.borderWidth:0,g=f/2,p=function(t){return Ut(n,t,f)};let m,x,b,_,y,v,M,w,k,S,P,D;if("top"===a)m=p(e.bottom),v=e.bottom-h,w=m-g,S=p(t.top)+g,D=t.bottom;else if("bottom"===a)m=p(e.top),S=t.top,D=p(t.bottom)-g,v=m+g,w=e.top+h;else if("left"===a)m=p(e.right),y=e.right-h,M=m-g,k=p(t.left)+g,P=t.right;else if("right"===a)m=p(e.left),k=t.left,P=p(t.right)-g,y=m+g,M=e.left+h;else if("x"===i){if("center"===a)m=p((t.top+t.bottom)/2+.5);else if(U(a)){const t=Object.keys(a)[0],i=a[t];m=p(e.chart.scales[t].getPixelForValue(i))}S=t.top,D=t.bottom,v=m+g,w=v+h}else if("y"===i){if("center"===a)m=p((t.left+t.right)/2);else if(U(a)){const t=Object.keys(a)[0],i=a[t];m=p(e.chart.scales[t].getPixelForValue(i))}y=m-g,M=y-h,k=t.left,P=t.right}for(x=0;xe.value===t));if(n>=0){return i.setContext(e.getContext(n)).lineWidth}return 0}drawGrid(t){const e=this,i=e.options.grid,n=e.ctx,o=e.chart,s=i.setContext(e.getContext(0)),a=i.drawBorder?s.borderWidth:0,r=e._gridLineItems||(e._gridLineItems=e._computeGridLineItems(t));let l,c;const h=(t,e,i)=>{i.width&&i.color&&(n.save(),n.lineWidth=i.width,n.strokeStyle=i.color,n.setLineDash(i.borderDash||[]),n.lineDashOffset=i.borderDashOffset,n.beginPath(),n.moveTo(t.x,t.y),n.lineTo(e.x,e.y),n.stroke(),n.restore())};if(i.display)for(l=0,c=r.length;l$i([o,...t],e,i,n)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,n)=>Ki(i,n,(()=>function(t,e,i,n){let o;for(const s of e)if(o=en(Xi(s,t),i),ht(o))return qi(t,o)?Ji(i,n,t,o):o}(n,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>nn(t).includes(e),ownKeys:t=>nn(t),set:(e,i,n)=>(t[0][i]=n,delete e[i],delete e._keys,!0)})}function Yi(t,e,i,n){const o={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:Ui(t,n),setContext:e=>Yi(t,e,i,n),override:o=>Yi(t.override(o),e,i,n)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>Ki(t,e,(()=>function(t,e,i){const{_proxy:n,_context:o,_subProxy:s,_descriptors:a}=t;let r=n[e];dt(r)&&a.isScriptable(e)&&(r=function(t,e,i,n){const{_proxy:o,_context:s,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+[...r].join("->")+"->"+t);r.add(t),e=e(s,a||n),r.delete(t),U(e)&&(e=Ji(o._scopes,o,t,e));return e}(e,r,t,i));Y(r)&&r.length&&(r=function(t,e,i,n){const{_proxy:o,_context:s,_subProxy:a,_descriptors:r}=i;if(ht(s.index)&&n(t))e=e[s.index%e.length];else if(U(e[0])){const i=e,n=o._scopes.filter((t=>t!==i));e=[];for(const l of i){const i=Ji(n,o,t,l);e.push(Yi(i,s,a&&a[t],r))}}return e}(e,r,t,a.isIndexable));qi(e,r)&&(r=Yi(r,o,s&&s[e],a));return r}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,n)=>(t[i]=n,delete e[i],!0)})}function Ui(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:n=e.indexable,_allKeys:o=e.allKeys}=t;return{allKeys:o,scriptable:i,indexable:n,isScriptable:dt(i)?i:()=>i,isIndexable:dt(n)?n:()=>n}}const Xi=(t,e)=>t?t+ct(e):e,qi=(t,e)=>U(e)&&"adapters"!==t;function Ki(t,e,i){let n=t[e];return ht(n)||(n=i(),ht(n)&&(t[e]=n)),n}function Gi(t,e,i){return dt(t)?t(e,i):t}const Zi=(t,e)=>!0===t?e:"string"==typeof t?lt(e,t):void 0;function Qi(t,e,i,n){for(const o of e){const e=Zi(i,o);if(e){t.add(e);const o=Gi(e._fallback,i,e);if(ht(o)&&o!==i&&o!==n)return o}else if(!1===e&&ht(n)&&i!==n)return null}return!1}function Ji(t,e,i,n){const o=e._rootScopes,s=Gi(e._fallback,i,n),a=[...t,...o],r=new Set,l=t[0];U(l)&&!(i in l)&&r.add(l[i]={}),r.add(n);let c=tn(r,a,i,s||i);return null!==c&&((!ht(s)||s===i||(c=tn(r,a,s,c),null!==c))&&$i([...r],[""],o,s))}function tn(t,e,i,n){for(;i;)i=Qi(t,e,i,n);return i}function en(t,e){for(const i of e){if(!i)continue;const e=i[t];if(ht(e))return e}}function nn(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return[...e]}(t._scopes)),e}const on=Number.EPSILON||1e-14,sn=(t,e)=>e!t.skip))),"monotone"===e.cubicInterpolationMode)rn(t);else{let i=n?t[t.length-1]:t[0];for(o=0,s=t.length;o0?e.y:t.y}}function un(t,e,i,n){const o={x:t.cp2x,y:t.cp2y},s={x:e.cp1x,y:e.cp1y},a=hn(t,o,i),r=hn(o,s,i),l=hn(s,e,i),c=hn(a,r,i),h=hn(r,l,i);return hn(c,h,i)}function fn(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function gn(t,e){let i,n;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,n=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=n)}function pn(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function mn(t){return"angle"===t?{between:Wt,compare:Vt,normalize:Bt}:{between:(t,e,i)=>t>=e&&t<=i,compare:(t,e)=>t-e,normalize:t=>t}}function xn(t,e,i,n){return{start:t%n,end:e%n,loop:i&&(e-t+1)%n==0}}function bn(t,e,i){if(!i)return[t];const{property:n,start:o,end:s}=i,a=e.length,{compare:r,between:l,normalize:c}=mn(n),{start:h,end:d,loop:u}=function(t,e,i){const{property:n,start:o,end:s}=i,{between:a,normalize:r}=mn(n),l=e.length;let c,h,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,c=0,h=l;cx||l(o,m,g)&&0!==r(o,m),y=()=>!x||0===r(s,g)||l(s,m,g);for(let t=h,i=h;t<=d;++t)p=e[t%a],p.skip||(g=c(p[n]),x=l(g,o,s),null===b&&_()&&(b=0===r(g,o)?t:i),null!==b&&y()&&(f.push(xn(b,t,u,a)),b=null),i=t,m=g);return null!==b&&f.push(xn(b,d,u,a)),f}function _n(t,e){const i=[],n=t.segments;for(let o=0;oo&&t[s%e].skip;)s--;return s%=e,{start:o,end:s}}(e,n,o,i);if(!0===i)return[{start:s,end:a,loop:o}];return function(t,e,i,n){const o=t.length,s=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%o];i.skip||i.stop?l.skip||(n=!1,s.push({start:e%o,end:(a-1)%o,loop:n}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&s.push({start:e%o,end:r%o,loop:n}),s}(e,s,a{const n=i.split("."),o=n.pop(),s=[t].concat(n).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");mt.route(s,o,l,r)}))}(e,t.defaultRoutes);t.descriptors&&mt.describe(e,t.descriptors)}(t,a,n),e.override&&mt.override(t.id,t.overrides)),a}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,n=this.scope;i in e&&delete e[i],n&&i in mt[n]&&(delete mt[n][i],this.override&&delete ut[i])}}var wn=new class{constructor(){this.controllers=new Mn(Ai,"datasets",!0),this.elements=new Mn(Oi,"elements"),this.plugins=new Mn(Object,"plugins"),this.scales=new Mn(ji,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){const n=this;[...e].forEach((e=>{const o=i||n._getRegistryForType(e);i||o.isForType(e)||o===n.plugins&&e.id?n._exec(t,o,e):J(e,(e=>{const o=i||n._getRegistryForType(e);n._exec(t,o,e)}))}))}_exec(t,e,i){const n=ct(t);Q(i["before"+n],[],i),e[t](i),Q(i["after"+n],[],i)}_getRegistryForType(t){for(let e=0;et.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(n(e,i),t,"stop"),this._notify(n(i,e),t,"start")}}function Sn(t,e){return e||!1!==t?!0===t?{}:t:null}function Pn(t,e,i,n){const o=t.pluginScopeKeys(e),s=t.getOptionScopes(i,o);return t.createResolver(s,n,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function Dn(t,e){const i=mt.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Cn(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function An(t){const e=t.options||(t.options={});e.plugins=K(e.plugins,{}),e.scales=function(t,e){const i=ut[t.type]||{scales:{}},n=e.scales||{},o=Dn(t.type,e),s=Object.create(null),a=Object.create(null);return Object.keys(n).forEach((t=>{const e=n[t],r=Cn(t,e),l=function(t,e){return t===e?"_index_":"_value_"}(r,o),c=i.scales||{};s[r]=s[r]||t,a[t]=st(Object.create(null),[{axis:r},e,c[r],c[l]])})),t.data.datasets.forEach((i=>{const o=i.type||t.type,r=i.indexAxis||Dn(o,e),l=(ut[o]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,r),o=i[e+"AxisID"]||s[e]||e;a[o]=a[o]||Object.create(null),st(a[o],[{axis:e},n[o],l[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];st(e,[mt.scales[e.type],mt.scale])})),a}(t,e)}const On=new Map,Tn=new Set;function Ln(t,e){let i=On.get(t);return i||(i=e(),On.set(t,i),Tn.add(i)),i}const Rn=(t,e,i)=>{const n=lt(e,i);void 0!==n&&t.add(n)};class En{constructor(t){this._config=function(t){const e=(t=t||{}).data=t.data||{datasets:[],labels:[]};return e.datasets=e.datasets||[],e.labels=e.labels||[],An(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=t}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),An(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return Ln(t,(()=>[["datasets."+t,""]]))}datasetAnimationScopeKeys(t,e){return Ln(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,"transitions."+e],["datasets."+t,""]]))}datasetElementScopeKeys(t,e){return Ln(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,"datasets."+t,"elements."+e,""]]))}pluginScopeKeys(t){const e=t.id;return Ln(`${this.type}-plugin-${e}`,(()=>[["plugins."+e,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let n=i.get(t);return n&&!e||(n=new Map,i.set(t,n)),n}getOptionScopes(t,e,i){const{options:n,type:o}=this,s=this._cachedScopes(t,i),a=s.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>Rn(r,t,e)))),e.forEach((t=>Rn(r,n,t))),e.forEach((t=>Rn(r,ut[o]||{},t))),e.forEach((t=>Rn(r,mt,t))),e.forEach((t=>Rn(r,ft,t)))}));const l=[...r];return Tn.has(e)&&s.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,ut[e]||{},mt.datasets[e]||{},{type:e},mt,ft]}resolveNamedOptions(t,e,i,n=[""]){const o={$shared:!0},{resolver:s,subPrefixes:a}=In(this._resolverCache,t,n);let r=s;if(function(t,e){const{isScriptable:i,isIndexable:n}=Ui(t);for(const o of e)if(i(o)&&dt(t[o])||n(o)&&Y(t[o]))return!0;return!1}(s,e)){o.$shared=!1;r=Yi(s,i=dt(i)?i():i,this.createResolver(t,i,a))}for(const t of e)o[t]=r[t];return o}createResolver(t,e,i=[""],n){const{resolver:o}=In(this._resolverCache,t,i);return U(e)?Yi(o,e,void 0,n):o}}function In(t,e,i){let n=t.get(e);n||(n=new Map,t.set(e,n));const o=i.join();let s=n.get(o);if(!s){s={resolver:$i(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},n.set(o,s)}return s}const Fn=["top","bottom","left","right","chartArea"];function zn(t,e){return"top"===t||"bottom"===t||-1===Fn.indexOf(t)&&"x"===e}function Vn(t,e){return function(i,n){return i[t]===n[t]?i[e]-n[e]:i[t]-n[t]}}function Bn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),Q(i&&i.onComplete,[t],e)}function Wn(t){const e=t.chart,i=e.options.animation;Q(i&&i.onProgress,[t],e)}function Hn(){return"undefined"!=typeof window&&"undefined"!=typeof document}function Nn(t){return Hn()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const jn={},$n=t=>{const e=Nn(t);return Object.values(jn).filter((t=>t.canvas===e)).pop()};class Yn{constructor(t,e){const n=this;this.config=e=new En(e);const o=Nn(t),s=$n(o);if(s)throw new Error("Canvas is already in use. Chart with ID '"+s.id+"' must be destroyed before the canvas can be reused.");const r=e.createResolver(e.chartOptionScopes(),n.getContext());this.platform=n._initializePlatform(o,e);const l=n.platform.acquireContext(o,r.aspectRatio),c=l&&l.canvas,h=c&&c.height,d=c&&c.width;this.id=j(),this.ctx=l,this.canvas=c,this.width=d,this.height=h,this._options=r,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._sortedMetasets=[],this.scales={},this.scale=void 0,this._plugins=new kn,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=i((()=>this.update("resize")),r.resizeDelay||0),jn[n.id]=n,l&&c?(a.listen(n,"complete",Bn),a.listen(n,"progress",Wn),n._initialize(),n.attached&&n.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:n,_aspectRatio:o}=this;return $(t)?e&&o?o:n?i/n:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){const t=this;return t.notifyPlugins("beforeInit"),t.options.responsive?t.resize():be(t,t.options.devicePixelRatio),t.bindEvents(),t.notifyPlugins("afterInit"),t}_initializePlatform(t,e){return e.platform?new e.platform:!Hn()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?new Ke:new li}clear(){return Xt(this.canvas,this.ctx),this}stop(){return a.stop(this),this}resize(t,e){a.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this,n=i.options,o=i.canvas,s=n.maintainAspectRatio&&i.aspectRatio,a=i.platform.getMaximumSize(o,t,e,s),r=i.currentDevicePixelRatio,l=n.devicePixelRatio||i.platform.getDevicePixelRatio();i.width===a.width&&i.height===a.height&&r===l||(i.width=a.width,i.height=a.height,i._aspectRatio=i.aspectRatio,be(i,l,!0),i.notifyPlugins("resize",{size:a}),Q(n.onResize,[i,a],i),i.attached&&i._doResize()&&i.render())}ensureScalesHaveIDs(){J(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this,e=t.options,i=e.scales,n=t.scales,o=Object.keys(n).reduce(((t,e)=>(t[e]=!1,t)),{});let s=[];i&&(s=s.concat(Object.keys(i).map((t=>{const e=i[t],n=Cn(t,e),o="r"===n,s="x"===n;return{options:e,dposition:o?"chartArea":s?"bottom":"left",dtype:o?"radialLinear":s?"category":"linear"}})))),J(s,(i=>{const s=i.options,a=s.id,r=Cn(a,s),l=K(s.type,i.dtype);void 0!==s.position&&zn(s.position,r)===zn(i.dposition)||(s.position=i.dposition),o[a]=!0;let c=null;if(a in n&&n[a].type===l)c=n[a];else{c=new(wn.getScale(l))({id:a,type:l,ctx:t.ctx,chart:t}),n[c.id]=c}c.init(s,e)})),J(o,((t,e)=>{t||delete n[e]})),J(n,(e=>{Xe.configure(t,e,e.options),Xe.addBox(t,e)}))}_updateMetasetIndex(t,e){const i=this._metasets,n=t.index;n!==e&&(i[n]=i[e],i[e]=t,t.index=e)}_updateMetasets(){const t=this,e=t._metasets,i=t.data.datasets.length,n=e.length;if(n>i){for(let e=i;ei.length&&delete t._stacks,e.forEach(((e,n)=>{0===i.filter((t=>t===e._dataset)).length&&t._destroyDatasetMeta(n)}))}buildOrUpdateControllers(){const t=this,e=[],i=t.data.datasets;let n,o;for(t._removeUnreferencedMetasets(),n=0,o=i.length;n{t.getDatasetMeta(i).controller.reset()}),t)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this,i=e.config;i.update(),e._options=i.createResolver(i.chartOptionScopes(),e.getContext()),J(e.scales,(t=>{Xe.removeBox(e,t)}));const n=e._animationsDisabled=!e.options.animation;if(e.ensureScalesHaveIDs(),e.buildOrUpdateScales(),e._plugins.invalidate(),!1===e.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const o=e.buildOrUpdateControllers();e.notifyPlugins("beforeElementsUpdate");let s=0;for(let t=0,i=e.data.datasets.length;t{t.reset()})),e._updateDatasets(t),e.notifyPlugins("afterUpdate",{mode:t}),e._layers.sort(Vn("z","_idx")),e._lastEvent&&e._eventHandler(e._lastEvent,!0),e.render()}_updateLayout(t){const e=this;if(!1===e.notifyPlugins("beforeLayout",{cancelable:!0}))return;Xe.update(e,e.width,e.height,t);const i=e.chartArea,n=i.width<=0||i.height<=0;e._layers=[],J(e.boxes,(t=>{n&&"chartArea"===t.position||(t.configure&&t.configure(),e._layers.push(...t._layers()))}),e),e._layers.forEach(((t,e)=>{t._idx=e})),e.notifyPlugins("afterLayout")}_updateDatasets(t){const e=this,i="function"==typeof t;if(!1!==e.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let n=0,o=e.data.datasets.length;n=0;--i)t._drawDataset(e[i]);t.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this,i=e.ctx,n=t._clip,o=e.chartArea,s={meta:t,index:t.index,cancelable:!0};!1!==e.notifyPlugins("beforeDatasetDraw",s)&&(Gt(i,{left:!1===n.left?0:o.left-n.left,right:!1===n.right?e.width:o.right+n.right,top:!1===n.top?0:o.top-n.top,bottom:!1===n.bottom?e.height:o.bottom+n.bottom}),t.controller.draw(),Zt(i),s.cancelable=!1,e.notifyPlugins("afterDatasetDraw",s))}getElementsAtEventForMode(t,e,i,n){const o=De.modes[e];return"function"==typeof o?o(this,t,i,n):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let n=i.filter((t=>t&&t._dataset===e)).pop();return n||(n=i[t]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1}),n}getContext(){return this.$context||(this.$context={chart:this,type:"chart"})}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateDatasetVisibility(t,e){const i=this,n=e?"show":"hide",o=i.getDatasetMeta(t),s=o.controller._resolveAnimations(void 0,n);i.setDatasetVisibility(t,e),s.update(o,{visible:e}),i.update((e=>e.datasetIndex===t?n:void 0))}hide(t){this._updateDatasetVisibility(t,!1)}show(t){this._updateDatasetVisibility(t,!0)}_destroyDatasetMeta(t){const e=this,i=e._metasets&&e._metasets[t];i&&i.controller&&(i.controller._destroy(),delete e._metasets[t])}destroy(){const t=this,{canvas:e,ctx:i}=t;let n,o;for(t.stop(),a.remove(t),n=0,o=t.data.datasets.length;n{i.addEventListener(t,n,o),e[n]=o},o=(n,o)=>{e[n]&&(i.removeEventListener(t,n,o),delete e[n])};let s=function(e,i,n){e.offsetX=i,e.offsetY=n,t._eventHandler(e)};if(J(t.options.events,(t=>n(t,s))),t.options.responsive){let e;s=(e,i)=>{t.canvas&&t.resize(e,i)};const a=()=>{o("attach",a),t.attached=!0,t.resize(),n("resize",s),n("detach",e)};e=()=>{t.attached=!1,o("resize",s),n("attach",a)},i.isAttached(t.canvas)?a():e()}else t.attached=!0}unbindEvents(){const t=this,e=t._listeners;e&&(delete t._listeners,J(e,((e,i)=>{t.platform.removeEventListener(t,i,e)})))}updateHoverStyle(t,e,i){const n=i?"set":"remove";let o,s,a,r;for("dataset"===e&&(o=this.getDatasetMeta(t[0].datasetIndex),o.controller["_"+n+"DatasetHoverStyle"]()),a=0,r=t.length;a{const n=e.getDatasetMeta(t);if(!n)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:n.data[i],index:i}}));!tt(n,i)&&(e._active=n,e._updateHoverStyles(n,i))}notifyPlugins(t,e){return this._plugins.notify(this,t,e)}_updateHoverStyles(t,e,i){const n=this,o=n.options.hover,s=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),a=s(e,t),r=i?t:s(t,e);a.length&&n.updateHoverStyle(a,o.mode,!1),r.length&&o.mode&&n.updateHoverStyle(r,o.mode,!0)}_eventHandler(t,e){const i=this,n={event:t,replay:e,cancelable:!0};if(!1===i.notifyPlugins("beforeEvent",n))return;const o=i._handleEvent(t,e);return n.cancelable=!1,i.notifyPlugins("afterEvent",n),(o||n.changed)&&i.render(),i}_handleEvent(t,e){const i=this,{_active:n=[],options:o}=i,s=o.hover,a=e;let r=[],l=!1,c=null;return"mouseout"!==t.type&&(r=i.getElementsAtEventForMode(t,s.mode,s,a),c="click"===t.type?i._lastEvent:t),i._lastEvent=null,Q(o.onHover,[t,r,i],i),"mouseup"!==t.type&&"click"!==t.type&&"contextmenu"!==t.type||Kt(t,i.chartArea,i._minPadding)&&Q(o.onClick,[t,r,i],i),l=!tt(r,n),(l||e)&&(i._active=r,i._updateHoverStyles(r,n,e)),i._lastEvent=c,l}}const Un=()=>J(Yn.instances,(t=>t._plugins.invalidate())),Xn=!0;function qn(){throw new Error("This method is not implemented: either no adapter can be found or an incomplete integration was provided.")}Object.defineProperties(Yn,{defaults:{enumerable:Xn,value:mt},instances:{enumerable:Xn,value:jn},overrides:{enumerable:Xn,value:ut},registry:{enumerable:Xn,value:wn},version:{enumerable:Xn,value:"3.0.2"},getChart:{enumerable:Xn,value:$n},register:{enumerable:Xn,value:(...t)=>{wn.add(...t),Un()}},unregister:{enumerable:Xn,value:(...t)=>{wn.remove(...t),Un()}}});class Kn{constructor(t){this.options=t||{}}formats(){return qn()}parse(t,e){return qn()}format(t,e){return qn()}add(t,e,i){return qn()}diff(t,e,i){return qn()}startOf(t,e,i){return qn()}endOf(t,e){return qn()}}Kn.override=function(t){Object.assign(Kn.prototype,t)};var Gn={_date:Kn};function Zn(t){const e=function(t){if(!t._cache.$bar){const e=t.getMatchingVisibleMetas("bar");let i=[];for(let n=0,o=e.length;nt-e)))}return t._cache.$bar}(t);let i,n,o,s,a=t._length;const r=()=>{a=Math.min(a,i&&Math.abs(o-s)||a),s=o};for(i=0,n=e.length;iMath.abs(r)&&(l=r,c=a),e[i.axis]=c,e._custom={barStart:l,barEnd:c,start:o,end:s,min:a,max:r}}(t,e,i,n):e[i.axis]=i.parse(t,n),e}function Jn(t,e,i,n){const o=t.iScale,s=t.vScale,a=o.getLabels(),r=o===s,l=[];let c,h,d,u;for(c=i,h=i+n;c0?(p+=t,h-=t):h<0&&(p-=t,h+=t)}return{size:h,base:p,head:c,center:c+h/2}}_calculateBarIndexPixels(t,e){const i=this,n=e.scale,o=i.options,s=K(o.maxBarThickness,1/0);let a,r;if(e.grouped){const n=o.skipNull?i._getStackCount(t):e.stackCount,l="flex"===o.barThickness?function(t,e,i,n){const o=e.pixels,s=o[t];let a=t>0?o[t-1]:null,r=t=0;--n)i=Math.max(i,t[n].size()/2,e[n]._custom);return i>0&&i}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:n}=e,o=this.getParsed(t),s=i.getLabelForValue(o.x),a=n.getLabelForValue(o.y),r=o._custom;return{label:e.label,value:"("+s+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,n){const o=this,s="reset"===n,{xScale:a,yScale:r}=o._cachedMeta,l=o.resolveDataElementOptions(e,n),c=o.getSharedOptions(l),h=o.includeOptions(n,c);for(let l=e;l""}}}};class no extends Ai{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,n=this._cachedMeta;let o,s;for(o=t,s=t+e;oWt(t,r,l)?1:Math.max(e,e*i,n,n*i),g=(t,e,n)=>Wt(t,r,l)?-1:Math.min(e,e*i,n,n*i),p=f(0,c,d),m=f(Mt,h,u),x=g(xt,c,d),b=g(xt+Mt,h,u);n=(p-x)/2,o=(m-b)/2,s=-(p+x)/2,a=-(m+b)/2}return{ratioX:n,ratioY:o,offsetX:s,offsetY:a}}(d,h,l),m=(n.width-a)/u,x=(n.height-a)/f,b=Math.max(Math.min(m,x)/2,0),_=Z(e.options.radius,b),y=(_-Math.max(_*l,0))/e._getVisibleDatasetWeightTotal();e.offsetX=g*_,e.offsetY=p*_,o.total=e.calculateTotal(),e.outerRadius=_-y*e._getRingWeightOffset(e.index),e.innerRadius=Math.max(e.outerRadius-y*c,0),e.updateElements(s,0,s.length,t)}_circumference(t,e){const i=this,n=i.options,o=i._cachedMeta,s=i._getCircumference();return e&&n.animation.animateRotate||!this.chart.getDataVisibility(t)||null===o._parsed[t]?0:i.calculateCircumference(o._parsed[t]*s/bt)}updateElements(t,e,i,n){const o=this,s="reset"===n,a=o.chart,r=a.chartArea,l=a.options.animation,c=(r.left+r.right)/2,h=(r.top+r.bottom)/2,d=s&&l.animateScale,u=d?0:o.innerRadius,f=d?0:o.outerRadius,g=o.resolveDataElementOptions(e,n),p=o.getSharedOptions(g),m=o.includeOptions(n,p);let x,b=o._getRotation();for(x=0;x0&&!isNaN(t)?bt*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,n=i.data.labels||[],o=Li(e._parsed[t],i.options.locale);return{label:n[t]||"",value:o}}getMaxBorderWidth(t){const e=this;let i=0;const n=e.chart;let o,s,a,r,l;if(!t)for(o=0,s=n.data.datasets.length;o{const n=t.getDatasetMeta(0).controller.getStyle(i);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,hidden:!t.getDataVisibility(i),index:i}})):[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return Y(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class oo extends Ai{initialize(){this.enableOptionSharing=!0,super.initialize()}update(t){const e=this,i=e._cachedMeta,{dataset:n,data:o=[],_dataset:s}=i,a=e.chart._animationsDisabled;let{start:r,count:l}=function(t,e,i){const n=e.length;let o=0,s=n;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:c,max:h,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(o=Ht(Math.min(ie(r,a.axis,c).lo,i?n:ie(e,l,a.getPixelForValue(c)).lo),0,n-1)),s=u?Ht(Math.max(ie(r,a.axis,h).hi+1,i?0:ie(e,l,a.getPixelForValue(h)).hi+1),o,n)-o:n-o}return{start:o,count:s}}(i,o,a);if(e._drawStart=r,e._drawCount=l,function(t){const{xScale:e,yScale:i,_scaleRanges:n}=t,o={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!n)return t._scaleRanges=o,!0;const s=n.xmin!==e.min||n.xmax!==e.max||n.ymin!==i.min||n.ymax!==i.max;return Object.assign(n,o),s}(i)&&(r=0,l=o.length),n._decimated=!!s._decimated,n.points=o,"resize"!==t){const i=e.resolveDatasetElementOptions(t);e.options.showLine||(i.borderWidth=0),e.updateElement(n,void 0,{animated:!a,options:i},t)}e.updateElements(o,r,l,t)}updateElements(t,e,i,n){const o=this,s="reset"===n,{xScale:a,yScale:r,_stacked:l}=o._cachedMeta,c=o.resolveDataElementOptions(e,n),h=o.getSharedOptions(c),d=o.includeOptions(n,h),u=o.options.spanGaps,f=At(u)?u:Number.POSITIVE_INFINITY,g=o.chart._animationsDisabled||s||"none"===n;let p=e>0&&o.getParsed(e-1);for(let c=e;c0&&i.x-p.x>f,d&&(u.options=h||o.resolveDataElementOptions(c,n)),g||o.updateElement(e,c,u,n),p=i}o.updateSharedOptions(h,n,c)}getMaxOverflow(){const t=this,e=t._cachedMeta,i=e.dataset,n=i.options&&i.options.borderWidth||0,o=e.data||[];if(!o.length)return n;const s=o[0].size(t.resolveDataElementOptions(0)),a=o[o.length-1].size(t.resolveDataElementOptions(o.length-1));return Math.max(n,s,a)/2}draw(){this._cachedMeta.dataset.updateControlPoints(this.chart.chartArea),super.draw()}}oo.id="line",oo.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},oo.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class so extends Ai{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}_updateRadius(){const t=this,e=t.chart,i=e.chartArea,n=e.options,o=Math.min(i.right-i.left,i.bottom-i.top),s=Math.max(o/2,0),a=(s-Math.max(n.cutoutPercentage?s/100*n.cutoutPercentage:1,0))/e.getVisibleDatasetCount();t.outerRadius=s-a*t.index,t.innerRadius=t.outerRadius-a}updateElements(t,e,i,n){const o=this,s="reset"===n,a=o.chart,r=o.getDataset(),l=a.options.animation,c=o._cachedMeta.rScale,h=c.xCenter,d=c.yCenter,u=c.getIndexAngle(0)-.5*xt;let f,g=u;const p=360/o.countVisibleElements();for(f=0;f{!isNaN(t.data[n])&&this.chart.getDataVisibility(n)&&i++})),i}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?Rt(this.resolveDataElementOptions(t,e).angle||i):0}}so.id="polarArea",so.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},so.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(((e,i)=>{const n=t.getDatasetMeta(0).controller.getStyle(i);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,hidden:!t.getDataVisibility(i),index:i}})):[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class ao extends no{}ao.id="pie",ao.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class ro extends Ai{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}update(t){const e=this,i=e._cachedMeta,n=i.dataset,o=i.data||[],s=i.iScale.getLabels();if(n.points=o,"resize"!==t){const i=e.resolveDatasetElementOptions(t);e.options.showLine||(i.borderWidth=0);const a={_loop:!0,_fullLoop:s.length===o.length,options:i};e.updateElement(n,void 0,a,t)}e.updateElements(o,0,o.length,t)}updateElements(t,e,i,n){const o=this,s=o.getDataset(),a=o._cachedMeta.rScale,r="reset"===n;for(let l=e;l"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var co=Object.freeze({__proto__:null,BarController:eo,BubbleController:io,DoughnutController:no,LineController:oo,PolarAreaController:so,PieController:ao,RadarController:ro,ScatterController:lo});function ho(t,e){const{startAngle:i,endAngle:n,pixelMargin:o,x:s,y:a,outerRadius:r,innerRadius:l}=e;let c=o/r;t.beginPath(),t.arc(s,a,r,i-c,n+c),l>o?(c=o/l,t.arc(s,a,l,n+c,i-c,!0)):t.arc(s,a,o,n+Mt,i-Mt),t.closePath(),t.clip()}function uo(t,e){const{x:i,y:n,startAngle:o,endAngle:s,pixelMargin:a}=e,r=Math.max(e.outerRadius-a,0),l=e.innerRadius+a;t.beginPath(),t.arc(i,n,r,o,s),t.arc(i,n,l,s,o,!0),t.closePath()}function fo(t,e){const{x:i,y:n,startAngle:o,endAngle:s,pixelMargin:a,options:r}=e,l=e.outerRadius,c=e.innerRadius+a,h="inner"===r.borderAlign;r.borderWidth&&(h?(t.lineWidth=2*r.borderWidth,t.lineJoin="round"):(t.lineWidth=r.borderWidth,t.lineJoin="bevel"),e.fullCircles&&function(t,e,i){const{x:n,y:o,startAngle:s,endAngle:a,pixelMargin:r}=e,l=Math.max(e.outerRadius-r,0),c=e.innerRadius+r;let h;for(i&&(e.endAngle=e.startAngle+bt,ho(t,e),e.endAngle=a,e.endAngle===e.startAngle&&(e.endAngle+=bt,e.fullCircles--)),t.beginPath(),t.arc(n,o,c,s+bt,s,!0),h=0;h=bt||Wt(o,a,r))&&(s>=l&&s<=c)}getCenterPoint(t){const{x:e,y:i,startAngle:n,endAngle:o,innerRadius:s,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius"],t),r=(n+o)/2,l=(s+a)/2;return{x:e+Math.cos(r)*l,y:i+Math.sin(r)*l}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const e=this,i=e.options,n=i.offset||0;if(e.pixelMargin="inner"===i.borderAlign?.33:0,e.fullCircles=Math.floor(e.circumference/bt),!(0===e.circumference||e.innerRadius<0||e.outerRadius<0)){if(t.save(),n&&e.circumference(a+(c?r-t:t))%s,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=o[b(0)],t.moveTo(d.x,d.y)),h=0;h<=r;++h){if(d=o[b(h)],d.skip)continue;const e=d.x,i=d.y,n=0|e;n===u?(ig&&(g=i),m=(x*m+e)/++x):(_(),t.lineTo(e,i),u=n,x=0,f=g=i),p=i}_()}function _o(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||e.stepped||i)?bo:xo}go.id="arc",go.defaults={borderAlign:"center",borderColor:"#fff",borderWidth:2,offset:0,angle:void 0},go.defaultRoutes={backgroundColor:"backgroundColor"};const yo="function"==typeof Path2D?function(t,e,i,n){let o=e._path;o||(o=e._path=new Path2D,e.path(o,i,n)&&o.closePath()),t.stroke(o)}:function(t,e,i,n){t.beginPath(),e.path(t,i,n)&&t.closePath(),t.stroke()};class vo extends Oi{constructor(t){super(),this.animated=!0,this.options=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,t&&Object.assign(this,t)}updateControlPoints(t){const e=this,i=e.options;if(i.tension&&!i.stepped&&!e._pointsUpdated){const n=i.spanGaps?e._loop:e._fullLoop;cn(e._points,i,t,n),e._pointsUpdated=!0}}set points(t){const e=this;e._points=t,delete e._segments,delete e._path,e._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=yn(this))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this,n=i.options,o=t[e],s=i.points,a=_n(i,{property:e,start:o,end:o});if(!a.length)return;const r=[],l=function(t){return t.stepped?dn:t.tension?un:hn}(n);let c,h;for(c=0,h=a.length;c"borderDash"!==t&&"fill"!==t};class wo extends Oi{constructor(t){super(),this.options=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const n=this.options,{x:o,y:s}=this.getProps(["x","y"],i);return Math.pow(t-o,2)+Math.pow(e-s,2)t.x):Po(e,"bottom","top",t.base=a.left&&e<=a.right)&&(s||i>=a.top&&i<=a.bottom)}function To(t,e){const{x:i,y:n,w:o,h:s,radius:a}=e;t.arc(i+a.topLeft,n+a.topLeft,a.topLeft,-Mt,xt,!0),t.lineTo(i,n+s-a.bottomLeft),t.arc(i+a.bottomLeft,n+s-a.bottomLeft,a.bottomLeft,xt,Mt,!0),t.lineTo(i+o-a.bottomRight,n+s),t.arc(i+o-a.bottomRight,n+s-a.bottomRight,a.bottomRight,Mt,0,!0),t.lineTo(i+o,n+a.topRight),t.arc(i+o-a.topRight,n+a.topRight,a.topRight,0,-Mt,!0),t.lineTo(i+a.topLeft,n)}function Lo(t,e){t.rect(e.x,e.y,e.w,e.h)}wo.id="point",wo.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},wo.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class Ro extends Oi{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t){const e=this.options,{inner:i,outer:n}=Ao(this),o=(s=n.radius).topLeft||s.topRight||s.bottomLeft||s.bottomRight?To:Lo;var s;t.save(),n.w===i.w&&n.h===i.h||(t.beginPath(),o(t,n),t.clip(),o(t,i),t.fillStyle=e.borderColor,t.fill("evenodd")),t.beginPath(),o(t,i),t.fillStyle=e.backgroundColor,t.fill(),t.restore()}inRange(t,e,i){return Oo(this,t,e,i)}inXRange(t,e){return Oo(this,t,null,e)}inYRange(t,e){return Oo(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:n,horizontal:o}=this.getProps(["x","y","base","horizontal"],t);return{x:o?(e+n)/2:e,y:o?i:(i+n)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}Ro.id="bar",Ro.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,pointStyle:void 0},Ro.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var Eo=Object.freeze({__proto__:null,ArcElement:go,LineElement:vo,PointElement:wo,BarElement:Ro});function Io(t){t.data.datasets.forEach((t=>{if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}))}var Fo={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void Io(t);const n=t.width;t.data.datasets.forEach(((e,o)=>{const{_data:s,indexAxis:a}=e,r=t.getDatasetMeta(o),l=s||e.data;if("y"===Ie([a,t.options.indexAxis]))return;if("line"!==r.type)return;const c=t.scales[r.xAxisID];if("linear"!==c.type&&"time"!==c.type)return;if(t.options.parsing)return;if(l.length<=4*n)return;let h;switch($(s)&&(e._data=l,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":h=function(t,e,i){const n=i.samples||e,o=[],s=(t.length-2)/(n-2);let a,r,l,c,h,d=0,u=0;for(o[d++]=t[u],a=0;al&&(l=c,r=t[e],h=e);o[d++]=r,u=h}return o[d++]=t[t.length-1],o}(l,n,i);break;case"min-max":h=function(t,e){let i,n,o,s,a,r,l,c,h,d,u=0,f=0;const g=[],p=t[0].x,m=t[t.length-1].x-p;for(i=0;id&&(d=s,l=i),u=(f*u+n.x)/++f;else{const e=i-1;if(!$(r)&&!$(l)){const i=Math.min(r,l),n=Math.max(r,l);i!==c&&i!==e&&g.push({...t[i],x:u}),n!==c&&n!==e&&g.push({...t[n],x:u})}i>0&&e!==c&&g.push(t[e]),g.push(n),a=x,f=0,h=d=s,r=l=c=i}}return g}(l,n);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=h}))},destroy(t){Io(t)}};function zo(t,e,i){const n=function(t){const e=t.options,i=e.fill;let n=K(i&&i.target,i);return void 0===n&&(n=!!e.backgroundColor),!1!==n&&null!==n&&(!0===n?"origin":n)}(t);if(U(n))return!isNaN(n.value)&&n;let o=parseFloat(n);return X(o)&&Math.floor(o)===o?("-"!==n[0]&&"+"!==n[0]||(o=e+o),!(o===e||o<0||o>=i)&&o):["origin","start","end","stack"].indexOf(n)>=0&&n}class Vo{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:n,y:o,radius:s}=this;return e=e||{start:0,end:bt},t.arc(n,o,s,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:n}=this,o=t.angle;return{x:e+Math.cos(o)*n,y:i+Math.sin(o)*n,angle:o}}}function Bo(t){return(t.scale||{}).getPointPositionForValue?function(t){const{scale:e,fill:i}=t,n=e.options,o=e.getLabels().length,s=[],a=n.reverse?e.max:e.min,r=n.reverse?e.min:e.max;let l,c,h;if(h="start"===i?a:"end"===i?r:U(i)?i.value:e.getBaseValue(),n.grid.circular)return c=e.getPointPositionForValue(0,a),new Vo({x:c.x,y:c.y,radius:e.getDistanceFromCenterForValue(h)});for(l=0;l"line"===t.type&&!t.hidden;function No(t,e,i){const n=[];for(let o=0;o=n&&o<=c){r=o===n,l=o===c;break}}return{first:r,last:l,point:n}}function $o(t,e){let i=[],n=!1;return Y(t)?(n=!0,i=t):i=function(t,e){const{x:i=null,y:n=null}=t||{},o=e.points,s=[];return e.segments.forEach((t=>{const e=o[t.start],a=o[t.end];null!==n?(s.push({x:e.x,y:n}),s.push({x:a.x,y:n})):null!==i&&(s.push({x:i,y:e.y}),s.push({x:i,y:a.y}))})),s}(t,e),i.length?new vo({points:i,options:{tension:0},_loop:n,_fullLoop:n}):null}function Yo(t,e,i){let n=t[e].fill;const o=[e];let s;if(!i)return n;for(;!1!==n&&-1===o.indexOf(n);){if(!X(n))return n;if(s=t[n],!s)return!1;if(s.visible)return n;o.push(n),n=s.fill}return!1}function Uo(t,e,i){t.beginPath(),e.path(t),t.lineTo(e.last().x,i),t.lineTo(e.first().x,i),t.closePath(),t.clip()}function Xo(t,e,i,n){if(n)return;let o=e[t],s=i[t];return"angle"===t&&(o=Bt(o),s=Bt(s)),{property:t,start:o,end:s}}function qo(t,e,i,n){return t&&e?n(t[i],e[i]):t?t[i]:e?e[i]:0}function Ko(t,e,i){const{top:n,bottom:o}=e.chart.chartArea,{property:s,start:a,end:r}=i||{};"x"===s&&(t.beginPath(),t.rect(a,n,r-a,o-n),t.clip())}function Go(t,e,i,n){const o=e.interpolate(i,n);o&&t.lineTo(o.x,o.y)}function Zo(t,e){const{line:i,target:n,property:o,color:s,scale:a}=e,r=function(t,e,i){const n=t.segments,o=t.points,s=e.points,a=[];for(let t=0;t=0;--n)o=e[n].$filler,o&&o.line.updateControlPoints(i)},beforeDatasetDraw(t,e){const i=t.chartArea,n=t.ctx,o=e.meta.$filler;if(!o||!1===o.fill)return;const s=function(t){const{chart:e,fill:i,line:n}=t;if(X(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return Wo(t);const o=Bo(t);return o instanceof Vo?o:$o(o,n)}(o),{line:a,scale:r}=o,l=a.options,c=l.fill,h=l.backgroundColor,{above:d=h,below:u=h}=c||{};s&&a.points.length&&(Gt(n,i),function(t,e){const{line:i,target:n,above:o,below:s,area:a,scale:r}=e,l=i._loop?"angle":"x";t.save(),"x"===l&&s!==o&&(Uo(t,n,a.top),Zo(t,{line:i,target:n,color:o,scale:r,property:l}),t.restore(),t.save(),Uo(t,n,a.bottom)),Zo(t,{line:i,target:n,color:s,scale:r,property:l}),t.restore()}(n,{line:a,target:s,above:d,below:u,area:i,scale:r}),Zt(n))},defaults:{propagate:!0}};const Jo=(t,e)=>{let{boxHeight:i=e,boxWidth:n=e}=t;return t.usePointStyle&&(i=Math.min(i,e),n=Math.min(n,e)),{boxWidth:n,boxHeight:i,itemHeight:Math.max(e,i)}};class ts extends Oi{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){const n=this;n.maxWidth=t,n.maxHeight=e,n._margins=i,n.setDimensions(),n.buildLabels(),n.fit()}setDimensions(){const t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height)}buildLabels(){const t=this,e=t.options.labels||{};let i=Q(e.generateLabels,[t.chart],t)||[];e.filter&&(i=i.filter((i=>e.filter(i,t.chart.data)))),e.sort&&(i=i.sort(((i,n)=>e.sort(i,n,t.chart.data)))),t.options.reverse&&i.reverse(),t.legendItems=i}fit(){const t=this,{options:e,ctx:i}=t;if(!e.display)return void(t.width=t.height=0);const n=e.labels,o=Ee(n.font),s=o.size,a=t._computeTitleHeight(),{boxWidth:r,itemHeight:l}=Jo(n,s);let c,h;i.font=o.string,t.isHorizontal()?(c=t.maxWidth,h=t._fitRows(a,s,r,l)+10):(h=t.maxHeight,c=t._fitCols(a,s,r,l)+10),t.width=Math.min(c,e.maxWidth||t.maxWidth),t.height=Math.min(h,e.maxHeight||t.maxHeight)}_fitRows(t,e,i,n){const o=this,{ctx:s,maxWidth:a,options:{labels:{padding:r}}}=o,l=o.legendHitBoxes=[],c=o.lineWidths=[0],h=n+r;let d=t;s.textAlign="left",s.textBaseline="middle";let u=-1,f=-h;return o.legendItems.forEach(((t,o)=>{const g=i+e/2+s.measureText(t.text).width;(0===o||c[c.length-1]+g+2*r>a)&&(d+=h,c[c.length-(o>0?0:1)]=0,f+=h,u++),l[o]={left:0,top:f,row:u,width:g,height:n},c[c.length-1]+=g+r})),d}_fitCols(t,e,i,n){const o=this,{ctx:s,maxHeight:a,options:{labels:{padding:r}}}=o,l=o.legendHitBoxes=[],c=o.columnSizes=[],h=a-t;let d=r,u=0,f=0,g=0,p=0,m=0;return o.legendItems.forEach(((t,o)=>{const a=i+e/2+s.measureText(t.text).width;o>0&&f+e+2*r>h&&(d+=u+r,c.push({width:u,height:f}),g+=u+r,m++,p=0,u=f=0),u=Math.max(u,a),f+=e+r,l[o]={left:g,top:p,col:m,width:a,height:n},p+=n+r})),d+=u,c.push({width:u,height:f}),d}adjustHitBoxes(){const t=this;if(!t.options.display)return;const e=t._computeTitleHeight(),{legendHitBoxes:i,options:{align:n,labels:{padding:s}}}=t;if(this.isHorizontal()){let a=0,r=o(n,t.left+s,t.right-t.lineWidths[a]);for(const l of i)a!==l.row&&(a=l.row,r=o(n,t.left+s,t.right-t.lineWidths[a])),l.top+=t.top+e+s,l.left=r,r+=l.width+s}else{let a=0,r=o(n,t.top+e+s,t.bottom-t.columnSizes[a].height);for(const l of i)l.col!==a&&(a=l.col,r=o(n,t.top+e+s,t.bottom-t.columnSizes[a].height)),l.top=r,l.left+=t.left+s,r+=l.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){const t=this;if(t.options.display){const e=t.ctx;Gt(e,t),t._draw(),Zt(e)}}_draw(){const t=this,{options:e,columnSizes:i,lineWidths:n,ctx:a}=t,{align:r,labels:l}=e,c=mt.color,h=fn(e.rtl,t.left,t.width),d=Ee(l.font),{color:u,padding:f}=l,g=d.size,p=g/2;let m;t.drawTitle(),a.textAlign=h.textAlign("left"),a.textBaseline="middle",a.lineWidth=.5,a.strokeStyle=u,a.fillStyle=u,a.font=d.string;const{boxWidth:x,boxHeight:b,itemHeight:_}=Jo(l,g),y=t.isHorizontal(),v=this._computeTitleHeight();m=y?{x:o(r,t.left+f,t.right-n[0]),y:t.top+f+v,line:0}:{x:t.left+f,y:o(r,t.top+v+f,t.bottom-i[0].height),line:0},gn(t.ctx,e.textDirection);const M=_+f;t.legendItems.forEach(((e,u)=>{const w=a.measureText(e.text).width,k=h.textAlign(e.textAlign||(e.textAlign=l.textAlign)),S=x+g/2+w;let P=m.x,D=m.y;h.setWidth(t.width),y?u>0&&P+S+f>t.right&&(D=m.y+=M,m.line++,P=m.x=o(r,t.left+f,t.right-n[m.line])):u>0&&D+M>t.bottom&&(P=m.x=P+i[m.line].width+f,m.line++,D=m.y=o(r,t.top+v+f,t.bottom-i[m.line].height));!function(t,e,i){if(isNaN(x)||x<=0||isNaN(b)||b<0)return;a.save();const n=K(i.lineWidth,1);if(a.fillStyle=K(i.fillStyle,c),a.lineCap=K(i.lineCap,"butt"),a.lineDashOffset=K(i.lineDashOffset,0),a.lineJoin=K(i.lineJoin,"miter"),a.lineWidth=n,a.strokeStyle=K(i.strokeStyle,c),a.setLineDash(K(i.lineDash,[])),l.usePointStyle){const o={radius:x*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},s=h.xPlus(t,x/2);qt(a,o,s,e+p)}else{const i=e+Math.max((g-b)/2,0);a.fillRect(h.leftForLtr(t,x),i,x,b),0!==n&&a.strokeRect(h.leftForLtr(t,x),i,x,b)}a.restore()}(h.x(P),D,e),P=s(k,P+x+p,t.right),function(t,e,i){te(a,i.text,t,e+_/2,d,{strikethrough:i.hidden,textAlign:i.textAlign})}(h.x(P),D,e),y?m.x+=S+f:m.y+=M})),pn(t.ctx,e.textDirection)}drawTitle(){const t=this,e=t.options,i=e.title,s=Ee(i.font),a=Re(i.padding);if(!i.display)return;const r=fn(e.rtl,t.left,t.width),l=t.ctx,c=i.position,h=s.size/2,d=a.top+h;let u,f=t.left,g=t.width;if(this.isHorizontal())g=Math.max(...t.lineWidths),u=t.top+d,f=o(e.align,f,t.right-g);else{const i=t.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);u=d+o(e.align,t.top,t.bottom-i-e.labels.padding-t._computeTitleHeight())}const p=o(c,f,f+g);l.textAlign=r.textAlign(n(c)),l.textBaseline="middle",l.strokeStyle=i.color,l.fillStyle=i.color,l.font=s.string,te(l,i.text,p,u,s)}_computeTitleHeight(){const t=this.options.title,e=Ee(t.font),i=Re(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){const i=this;let n,o,s;if(t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom)for(s=i.legendHitBoxes,n=0;n=o.left&&t<=o.left+o.width&&e>=o.top&&e<=o.top+o.height)return i.legendItems[n];return null}handleEvent(t){const e=this,i=e.options;if(!function(t,e){if("mousemove"===t&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,i))return;const n=e._getLegendItemAt(t.x,t.y);if("mousemove"===t.type){const a=e._hoveredItem,r=(s=n,null!==(o=a)&&null!==s&&o.datasetIndex===s.datasetIndex&&o.index===s.index);a&&!r&&Q(i.onLeave,[t,a,e],e),e._hoveredItem=n,n&&!r&&Q(i.onHover,[t,n,e],e)}else n&&Q(i.onClick,[t,n,e],e);var o,s}}var es={id:"legend",_element:ts,start(t,e,i){const n=t.legend=new ts({ctx:t.ctx,options:i,chart:t});Xe.configure(t,n,i),Xe.addBox(t,n)},stop(t){Xe.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const n=t.legend;Xe.configure(t,n,i),n.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const n=e.datasetIndex,o=i.chart;o.isDatasetVisible(n)?(o.hide(n),e.hidden=!0):(o.show(n),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:n,textAlign:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const s=t.controller.getStyle(i?0:void 0),a=Re(s.borderWidth);return{text:e[t.index].label,fillStyle:s.backgroundColor,hidden:!t.visible,lineCap:s.borderCapStyle,lineDash:s.borderDash,lineDashOffset:s.borderDashOffset,lineJoin:s.borderJoinStyle,lineWidth:(a.width+a.height)/4,strokeStyle:s.borderColor,pointStyle:n||s.pointStyle,rotation:s.rotation,textAlign:o||s.textAlign,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class is extends Oi{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this,n=i.options;if(i.left=0,i.top=0,!n.display)return void(i.width=i.height=i.right=i.bottom=0);i.width=i.right=t,i.height=i.bottom=e;const o=Y(n.text)?n.text.length:1;i._padding=Re(n.padding);const s=o*Ee(n.font).lineHeight+i._padding.height;i.isHorizontal()?i.height=s:i.width=s}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:n,right:s,options:a}=this,r=a.align;let l,c,h,d=0;return this.isHorizontal()?(c=o(r,i,s),h=e+t,l=s-i):("left"===a.position?(c=i+t,h=o(r,n,e),d=-.5*xt):(c=s-t,h=o(r,e,n),d=.5*xt),l=n-e),{titleX:c,titleY:h,maxWidth:l,rotation:d}}draw(){const t=this,e=t.ctx,i=t.options;if(!i.display)return;const o=Ee(i.font),s=o.lineHeight/2+t._padding.top,{titleX:a,titleY:r,maxWidth:l,rotation:c}=t._drawArgs(s);te(e,i.text,0,0,o,{color:i.color,maxWidth:l,rotation:c,textAlign:n(i.align),textBaseline:"middle",translation:[a,r]})}}var ns={id:"title",_element:is,start(t,e,i){!function(t,e){const i=new is({ctx:t.ctx,options:e,chart:t});Xe.configure(t,i,e),Xe.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;Xe.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const n=t.titleBlock;Xe.configure(t,n,i),n.options=i},defaults:{align:"center",display:!1,font:{style:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const os={average(t){if(!t.length)return!1;let e,i,n=0,o=0,s=0;for(e=0,i=t.length;e-1?t.split("\n"):t}function rs(t,e){const{element:i,datasetIndex:n,index:o}=e,s=t.getDatasetMeta(n).controller,{label:a,value:r}=s.getLabelAndValue(o);return{chart:t,label:a,parsed:s.getParsed(o),raw:t.data.datasets[n].data[o],formattedValue:r,dataset:s.getDataset(),dataIndex:o,datasetIndex:n,element:i}}function ls(t,e){const i=t._chart.ctx,{body:n,footer:o,title:s}=t,{boxWidth:a,boxHeight:r}=e,l=Ee(e.bodyFont),c=Ee(e.titleFont),h=Ee(e.footerFont),d=s.length,u=o.length,f=n.length,g=Re(e.padding);let p=g.height,m=0,x=n.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,d&&(p+=d*c.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),x){p+=f*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-f)*l.lineHeight+(x-1)*e.bodySpacing}u&&(p+=e.footerMarginTop+u*h.lineHeight+(u-1)*e.footerSpacing);let b=0;const _=function(t){m=Math.max(m,i.measureText(t).width+b)};return i.save(),i.font=c.string,J(t.title,_),i.font=l.string,J(t.beforeBody.concat(t.afterBody),_),b=e.displayColors?a+2:0,J(n,(t=>{J(t.before,_),J(t.lines,_),J(t.after,_)})),b=0,i.font=h.string,J(t.footer,_),i.restore(),m+=g.width,{width:m,height:p}}function cs(t,e,i,n){const{x:o,width:s}=i,{width:a,chartArea:{left:r,right:l}}=t;let c="center";return"center"===n?c=o<=(r+l)/2?"left":"right":o<=s/2?c="left":o>=a-s/2&&(c="right"),function(t,e,i,n){const{x:o,width:s}=n,a=i.caretSize+i.caretPadding;return"left"===t&&o+s+a>e.width||"right"===t&&o-s-a<0||void 0}(c,t,e,i)&&(c="center"),c}function hs(t,e,i){const n=e.yAlign||function(t,e){const{y:i,height:n}=e;return it.height-n/2?"bottom":"center"}(t,i);return{xAlign:e.xAlign||cs(t,e,i,n),yAlign:n}}function ds(t,e,i,n){const{caretSize:o,caretPadding:s,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,c=o+s,h=a+s;let d=function(t,e){let{x:i,width:n}=t;return"right"===e?i-=n:"center"===e&&(i-=n/2),i}(e,r);const u=function(t,e,i){let{y:n,height:o}=t;return"top"===e?n+=i:n-="bottom"===e?o+i:o/2,n}(e,l,c);return"center"===l?"left"===r?d+=c:"right"===r&&(d-=c):"left"===r?d-=h:"right"===r&&(d+=h),{x:Ht(d,0,n.width-e.width),y:Ht(u,0,n.height-e.height)}}function us(t,e,i){const n=Re(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-n.right:t.x+n.left}function fs(t){return ss([],as(t))}function gs(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class ps extends Oi{constructor(t){super(),this.opacity=0,this._active=[],this._chart=t._chart,this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this,e=t._cachedAnimations;if(e)return e;const i=t._chart,n=t.options.setContext(t.getContext()),o=n.enabled&&i.options.animation&&n.animations,s=new bi(t._chart,o);return o._cacheable&&(t._cachedAnimations=Object.freeze(s)),s}getContext(){const t=this;return t.$context||(t.$context=(e=t._chart.getContext(),i=t,n=t._tooltipItems,Object.assign(Object.create(e),{tooltip:i,tooltipItems:n,type:"tooltip"})));var e,i,n}getTitle(t,e){const i=this,{callbacks:n}=e,o=n.beforeTitle.apply(i,[t]),s=n.title.apply(i,[t]),a=n.afterTitle.apply(i,[t]);let r=[];return r=ss(r,as(o)),r=ss(r,as(s)),r=ss(r,as(a)),r}getBeforeBody(t,e){return fs(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const i=this,{callbacks:n}=e,o=[];return J(t,(t=>{const e={before:[],lines:[],after:[]},s=gs(n,t);ss(e.before,as(s.beforeLabel.call(i,t))),ss(e.lines,s.label.call(i,t)),ss(e.after,as(s.afterLabel.call(i,t))),o.push(e)})),o}getAfterBody(t,e){return fs(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const i=this,{callbacks:n}=e,o=n.beforeFooter.apply(i,[t]),s=n.footer.apply(i,[t]),a=n.afterFooter.apply(i,[t]);let r=[];return r=ss(r,as(o)),r=ss(r,as(s)),r=ss(r,as(a)),r}_createItems(t){const e=this,i=e._active,n=e._chart.data,o=[],s=[],a=[];let r,l,c=[];for(r=0,l=i.length;rt.filter(e,i,o,n)))),t.itemSort&&(c=c.sort(((e,i)=>t.itemSort(e,i,n)))),J(c,(i=>{const n=gs(t.callbacks,i);o.push(n.labelColor.call(e,i)),s.push(n.labelPointStyle.call(e,i)),a.push(n.labelTextColor.call(e,i))})),e.labelColors=o,e.labelPointStyles=s,e.labelTextColors=a,e.dataPoints=c,c}update(t,e){const i=this,n=i.options.setContext(i.getContext()),o=i._active;let s,a=[];if(o.length){const t=os[n.position].call(i,o,i._eventPosition);a=i._createItems(n),i.title=i.getTitle(a,n),i.beforeBody=i.getBeforeBody(a,n),i.body=i.getBody(a,n),i.afterBody=i.getAfterBody(a,n),i.footer=i.getFooter(a,n);const e=i._size=ls(i,n),r=Object.assign({},t,e),l=hs(i._chart,n,r),c=ds(n,r,l,i._chart);i.xAlign=l.xAlign,i.yAlign=l.yAlign,s={opacity:1,x:c.x,y:c.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==i.opacity&&(s={opacity:0});i._tooltipItems=a,i.$context=void 0,s&&i._resolveAnimations().update(i,s),t&&n.external&&n.external.call(i,{chart:i._chart,tooltip:i,replay:e})}drawCaret(t,e,i,n){const o=this.getCaretPosition(t,i,n);e.lineTo(o.x1,o.y1),e.lineTo(o.x2,o.y2),e.lineTo(o.x3,o.y3)}getCaretPosition(t,e,i){const{xAlign:n,yAlign:o}=this,{cornerRadius:s,caretSize:a}=i,{x:r,y:l}=t,{width:c,height:h}=e;let d,u,f,g,p,m;return"center"===o?(p=l+h/2,"left"===n?(d=r,u=d-a,g=p+a,m=p-a):(d=r+c,u=d+a,g=p-a,m=p+a),f=d):(u="left"===n?r+s+a:"right"===n?r+c-s-a:this.caretX,"top"===o?(g=l,p=g-a,d=u-a,f=u+a):(g=l+h,p=g+a,d=u+a,f=u-a),m=g),{x1:d,x2:u,x3:f,y1:g,y2:p,y3:m}}drawTitle(t,e,i){const n=this,o=n.title,s=o.length;let a,r,l;if(s){const c=fn(i.rtl,n.x,n.width);for(t.x=us(n,i.titleAlign,i),e.textAlign=c.textAlign(i.titleAlign),e.textBaseline="middle",a=Ee(i.titleFont),r=i.titleSpacing,e.fillStyle=i.titleColor,e.font=a.string,l=0;l0&&e.stroke()}_updateAnimationTarget(t){const e=this,i=e._chart,n=e.$animations,o=n&&n.x,s=n&&n.y;if(o||s){const n=os[t.position].call(e,e._active,e._eventPosition);if(!n)return;const a=e._size=ls(e,t),r=Object.assign({},n,e._size),l=hs(i,t,r),c=ds(t,r,l,i);o._to===c.x&&s._to===c.y||(e.xAlign=l.xAlign,e.yAlign=l.yAlign,e.width=a.width,e.height=a.height,e.caretX=n.x,e.caretY=n.y,e._resolveAnimations().update(e,c))}}draw(t){const e=this,i=e.options.setContext(e.getContext());let n=e.opacity;if(!n)return;e._updateAnimationTarget(i);const o={width:e.width,height:e.height},s={x:e.x,y:e.y};n=Math.abs(n)<.001?0:n;const a=Re(i.padding),r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;i.enabled&&r&&(t.save(),t.globalAlpha=n,e.drawBackground(s,t,o,i),gn(t,i.textDirection),s.y+=a.top,e.drawTitle(s,t,i),e.drawBody(s,t,i),e.drawFooter(s,t,i),pn(t,i.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this,n=i._active,o=t.map((({datasetIndex:t,index:e})=>{const n=i._chart.getDatasetMeta(t);if(!n)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:n.data[e],index:e}})),s=!tt(n,o),a=i._positionChanged(o,e);(s||a)&&(i._active=o,i._eventPosition=e,i.update(!0))}handleEvent(t,e){const i=this,n=i.options,o=i._active||[];let s=!1,a=[];"mouseout"!==t.type&&(a=i._chart.getElementsAtEventForMode(t,n.mode,n,e),n.reverse&&a.reverse());const r=i._positionChanged(a,t);return s=e||!tt(a,o)||r,s&&(i._active=a,(n.enabled||n.external)&&(i._eventPosition={x:t.x,y:t.y},i.update(!0,e))),s}_positionChanged(t,e){const i=this,n=os[i.options.position].call(i,t,e);return i.caretX!==n.x||i.caretY!==n.y}}ps.positioners=os;var ms={id:"tooltip",_element:ps,positioners:os,afterInit(t,e,i){i&&(t.tooltip=new ps({_chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip,i={tooltip:e};!1!==t.notifyPlugins("beforeTooltipDraw",i)&&(e&&e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i))},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{style:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{style:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:N,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,n=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(n>0&&e.dataIndex"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},xs=Object.freeze({__proto__:null,Decimation:Fo,Filler:Qo,Legend:es,Title:ns,Tooltip:ms});function bs(t,e,i){const n=t.indexOf(e);if(-1===n)return((t,e,i)=>"string"==typeof e?t.push(e)-1:isNaN(e)?null:i)(t,e,i);return n!==t.lastIndexOf(e)?i:n}class _s extends ji{constructor(t){super(t),this._startValue=void 0,this._valueRange=0}parse(t,e){if($(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:Ht(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:bs(i,t,K(e,t)),i.length-1)}determineDataLimits(){const t=this,{minDefined:e,maxDefined:i}=t.getUserBounds();let{min:n,max:o}=t.getMinMax(!0);"ticks"===t.options.bounds&&(e||(n=0),i||(o=t.getLabels().length-1)),t.min=n,t.max=o}buildTicks(){const t=this,e=t.min,i=t.max,n=t.options.offset,o=[];let s=t.getLabels();s=0===e&&i===s.length-1?s:s.slice(e,i+1),t._valueRange=Math.max(s.length-(n?0:1),1),t._startValue=t.min-(n?.5:0);for(let t=e;t<=i;t++)o.push({value:t});return o}getLabelForValue(t){const e=this.getLabels();return t>=0&&te.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){const e=this;return Math.round(e._startValue+e.getDecimalForPixel(t)*e._valueRange)}getBasePixel(){return this.bottom}}_s.id="category",_s.defaults={ticks:{callback:_s.prototype.getLabelForValue}};class ys extends ji{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return $(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const t=this,{beginAtZero:e,stacked:i}=t.options,{minDefined:n,maxDefined:o}=t.getUserBounds();let{min:s,max:a}=t;const r=t=>s=n?s:t,l=t=>a=o?a:t;if(e||i){const t=Pt(s),e=Pt(a);t<0&&e<0?l(0):t>0&&e>0&&r(0)}s===a&&(l(a+1),e||r(s-1)),t.min=s,t.max=a}getTickLimit(){const t=this,e=t.options.ticks;let i,{maxTicksLimit:n,stepSize:o}=e;return o?i=Math.ceil(t.max/o)-Math.floor(t.min/o)+1:(i=t.computeTickLimit(),n=n||11),n&&(i=Math.min(n,i)),i}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this,e=t.options,i=e.ticks;let n=t.getTickLimit();n=Math.max(2,n);const o=function(t,e){const i=[],{step:n,min:o,max:s,precision:a,count:r,maxTicks:l}=t,c=n||1,h=l-1,{min:d,max:u}=e,f=!$(o),g=!$(s),p=!$(r);let m,x,b,_,y=Dt((u-d)/h/c)*c;if(y<1e-14&&!f&&!g)return[{value:d},{value:u}];_=Math.ceil(u/y)-Math.floor(d/y),_>h&&(y=Dt(_*y/h/c)*c),$(a)||(m=Math.pow(10,a),y=Math.ceil(y*m)/m),x=Math.floor(d/y)*y,b=Math.ceil(u/y)*y,f&&g&&n&&Tt((s-o)/n,y/1e3)?(_=Math.min((s-o)/y,l),y=(s-o)/_,x=o,b=s):p?(x=f?o:x,b=g?s:b,_=r-1,y=(b-x)/_):(_=(b-x)/y,_=Ot(_,Math.round(_),y/1e3)?Math.round(_):Math.ceil(_)),m=Math.pow(10,$(a)?It(y):a),x=Math.round(x*m)/m,b=Math.round(b*m)/m;let v=0;for(f&&(i.push({value:o}),x<=o&&v++,Ot(Math.round((x+v*y)*m)/m,o,y/10)&&v++);v<_;++v)i.push({value:Math.round((x+v*y)*m)/m});return g?Ot(i[i.length-1].value,s,y/10)?i[i.length-1].value=s:i.push({value:s}):i.push({value:b}),i}({maxTicks:n,min:e.min,max:e.max,precision:i.precision,step:i.stepSize,count:i.count},Fe(t,e.grace));return"ticks"===e.bounds&&Lt(o,t,"value"),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),o}configure(){const t=this,e=t.ticks;let i=t.min,n=t.max;if(super.configure(),t.options.offset&&e.length){const t=(n-i)/Math.max(e.length-1,1)/2;i-=t,n+=t}t._startValue=i,t._endValue=n,t._valueRange=n-i}getLabelForValue(t){return Li(t,this.chart.options.locale)}}class vs extends ys{determineDataLimits(){const t=this,{min:e,max:i}=t.getMinMax(!0);t.min=X(e)?e:0,t.max=X(i)?i:1,t.handleTickRangeOptions()}computeTickLimit(){const t=this;if(t.isHorizontal())return Math.ceil(t.width/40);const e=t._resolveTickFontOptions(0);return Math.ceil(t.height/e.lineHeight)}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function Ms(t){return 1===t/Math.pow(10,Math.floor(St(t)))}vs.id="linear",vs.defaults={ticks:{callback:Ei.formatters.numeric}};class ws extends ji{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=ys.prototype.parse.apply(this,[t,e]);if(0!==i)return X(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const t=this,{min:e,max:i}=t.getMinMax(!0);t.min=X(e)?Math.max(0,e):null,t.max=X(i)?Math.max(0,i):null,t.options.beginAtZero&&(t._zero=!0),t.handleTickRangeOptions()}handleTickRangeOptions(){const t=this,{minDefined:e,maxDefined:i}=t.getUserBounds();let n=t.min,o=t.max;const s=t=>n=e?n:t,a=t=>o=i?o:t,r=(t,e)=>Math.pow(10,Math.floor(St(t))+e);n===o&&(n<=0?(s(1),a(10)):(s(r(n,-1)),a(r(o,1)))),n<=0&&s(r(o,-1)),o<=0&&a(r(n,1)),t._zero&&t.min!==t._suggestedMin&&n===r(t.min,0)&&s(r(n,-1)),t.min=n,t.max=o}buildTicks(){const t=this,e=t.options,i=function(t,e){const i=Math.floor(St(e.max)),n=Math.ceil(e.max/Math.pow(10,i)),o=[];let s=q(t.min,Math.pow(10,Math.floor(St(e.min)))),a=Math.floor(St(s)),r=Math.floor(s/Math.pow(10,a)),l=a<0?Math.pow(10,Math.abs(a)):1;do{o.push({value:s,major:Ms(s)}),++r,10===r&&(r=1,++a,l=a>=0?1:l),s=Math.round(r*Math.pow(10,a)*l)/l}while(ao?{start:e-i,end:e}:{start:e,end:e+i}}function Ps(t){return 0===t||180===t?"center":t<180?"left":"right"}function Ds(t,e,i){90===t||270===t?i.y-=e.h/2:(t>270||t<90)&&(i.y-=e.h)}function Cs(t,e,i,n){const{ctx:o}=t;if(i)o.arc(t.xCenter,t.yCenter,e,0,bt);else{let i=t.getPointPosition(0,e);o.moveTo(i.x,i.y);for(let s=1;s{const n=Q(e.options.pointLabels.callback,[t,i],e);return n||0===n?n:""}))}fit(){const t=this,e=t.options;e.display&&e.pointLabels.display?function(t){const e={l:0,r:t.width,t:0,b:t.height-t.paddingTop},i={};let n,o,s;const a=[],r=[],l=t.getLabels().length;for(n=0;ne.r&&(e.r=p.end,i.r=f),m.starte.b&&(e.b=m.end,i.b=f)}var c,h,d;t._setReductions(t.drawingArea,e,i),t._pointLabelItems=[];const u=t.options,f=ks(u),g=t.getDistanceFromCenterForValue(u.ticks.reverse?t.min:t.max);for(n=0;n=0;o--){const e=n.setContext(t.getContext(o)),s=Ee(e.font),{x:a,y:r,textAlign:l,left:c,top:h,right:d,bottom:u}=t._pointLabelItems[o],{backdropColor:f}=e;if(!$(f)){const t=Re(e.backdropPadding);i.fillStyle=f,i.fillRect(c-t.left,h-t.top,d-c+t.width,u-h+t.height)}te(i,t._pointLabels[o],a,r+s.lineHeight/2,s,{color:e.color,textAlign:l,textBaseline:"middle"})}}(t,s),o.display&&t.ticks.forEach(((e,i)=>{if(0!==i){r=t.getDistanceFromCenterForValue(e.value);const n=o.setContext(t.getContext(i-1));!function(t,e,i,n){const o=t.ctx,s=e.circular,{color:a,lineWidth:r}=e;!s&&!n||!a||!r||i<0||(o.save(),o.strokeStyle=a,o.lineWidth=r,o.setLineDash(e.borderDash),o.lineDashOffset=e.borderDashOffset,o.beginPath(),Cs(t,i,s,n),o.closePath(),o.stroke(),o.restore())}(t,n,r,s)}})),n.display){for(e.save(),a=t.getLabels().length-1;a>=0;a--){const o=n.setContext(t.getContext(a)),{color:s,lineWidth:c}=o;c&&s&&(e.lineWidth=c,e.strokeStyle=s,e.setLineDash(o.borderDash),e.lineDashOffset=o.borderDashOffset,r=t.getDistanceFromCenterForValue(i.ticks.reverse?t.min:t.max),l=t.getPointPosition(a,r),e.beginPath(),e.moveTo(t.xCenter,t.yCenter),e.lineTo(l.x,l.y),e.stroke())}e.restore()}}drawLabels(){const t=this,e=t.ctx,i=t.options,n=i.ticks;if(!n.display)return;const o=t.getIndexAngle(0);let s,a;e.save(),e.translate(t.xCenter,t.yCenter),e.rotate(o),e.textAlign="center",e.textBaseline="middle",t.ticks.forEach(((o,r)=>{if(0===r&&!i.reverse)return;const l=n.setContext(t.getContext(r)),c=Ee(l.font);if(s=t.getDistanceFromCenterForValue(t.ticks[r].value),l.showLabelBackdrop){a=e.measureText(o.label).width,e.fillStyle=l.backdropColor;const t=Re(l.backdropPadding);e.fillRect(-a/2-t.left,-s-c.size/2-t.top,a+t.width,c.size+t.height)}te(e,o.label,0,-s,c,{color:l.color})})),e.restore()}drawTitle(){}}Os.id="radialLinear",Os.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPadding:2,callback:Ei.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5}},Os.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},Os.descriptors={angleLines:{_fallback:"grid"}};const Ts={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},Ls=Object.keys(Ts);function Rs(t,e){return t-e}function Es(t,e){if($(e))return null;const i=t._adapter,n=t.options.time,{parser:o,round:s,isoWeekday:a}=n;let r=e;return"function"==typeof o&&(r=o(r)),X(r)||(r="string"==typeof o?i.parse(r,o):i.parse(r)),null===r?null:(s&&(r="week"!==s||!At(a)&&!0!==a?i.startOf(r,s):i.startOf(r,"isoWeek",a)),+r)}function Is(t,e,i,n){const o=Ls.length;for(let s=Ls.indexOf(t);s=e?i[n]:i[o]]=!0}}else t[e]=!0}function zs(t,e,i){const n=[],o={},s=e.length;let a,r;for(a=0;a=0&&(e[l].major=!0);return e}(t,n,o,i):n}class Vs extends ji{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1}init(t,e){const i=t.time||(t.time={}),n=this._adapter=new Gn._date(t.adapters.date);st(i.displayFormats,n.formats()),super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:Es(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this,e=t.options,i=t._adapter,n=e.time.unit||"day";let{min:o,max:s,minDefined:a,maxDefined:r}=t.getUserBounds();function l(t){a||isNaN(t.min)||(o=Math.min(o,t.min)),r||isNaN(t.max)||(s=Math.max(s,t.max))}a&&r||(l(t._getLabelBounds()),"ticks"===e.bounds&&"labels"===e.ticks.source||l(t.getMinMax(!1))),o=X(o)&&!isNaN(o)?o:+i.startOf(Date.now(),n),s=X(s)&&!isNaN(s)?s:+i.endOf(Date.now(),n)+1,t.min=Math.min(o,s-1),t.max=Math.max(o+1,s)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this,e=t.options,i=e.time,n=e.ticks,o="labels"===n.source?t.getLabelTimestamps():t._generate();"ticks"===e.bounds&&o.length&&(t.min=t._userMin||o[0],t.max=t._userMax||o[o.length-1]);const s=t.min,a=oe(o,s,t.max);return t._unit=i.unit||(n.autoSkip?Is(i.minUnit,t.min,t.max,t._getLabelCapacity(s)):function(t,e,i,n,o){for(let s=Ls.length-1;s>=Ls.indexOf(i);s--){const i=Ls[s];if(Ts[i].common&&t._adapter.diff(o,n,i)>=e-1)return i}return Ls[i?Ls.indexOf(i):0]}(t,a.length,i.minUnit,t.min,t.max)),t._majorUnit=n.major.enabled&&"year"!==t._unit?function(t){for(let e=Ls.indexOf(t)+1,i=Ls.length;e1e5*r)throw new Error(i+" and "+n+" are too far apart with stepSize of "+r+" "+a);const g="data"===o.ticks.source&&t.getDataTimestamps();for(d=f,u=0;dt-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,n){const o=this,s=o.options,a=s.time.displayFormats,r=o._unit,l=o._majorUnit,c=r&&a[r],h=l&&a[l],d=i[e],u=l&&h&&d&&d.major,f=o._adapter.format(t,n||(u?h:c)),g=s.ticks.callback;return g?g(f,e,i):f}generateTickLabels(t){let e,i,n;for(e=0,i=t.length;e0?r:1}getDataTimestamps(){const t=this;let e,i,n=t._cache.data||[];if(n.length)return n;const o=t.getMatchingVisibleMetas();if(t._normalized&&o.length)return t._cache.data=o[0].controller.getAllParsedValues(t);for(e=0,i=o.length;ee&&a0&&!$(e)?e/i._maxIndex:i.getDecimalForValue(t);return i.getPixelForDecimal((n.start+o)*n.factor)}getDecimalForValue(t){return Bs(this._table,t)/this._maxIndex}getValueForPixel(t){const e=this,i=e._offsets,n=e.getDecimalForPixel(t)/i.factor-i.end;return Bs(e._table,n*this._maxIndex,!0)}}Ws.id="timeseries",Ws.defaults=Vs.defaults;var Hs=Object.freeze({__proto__:null,CategoryScale:_s,LinearScale:vs,LogarithmicScale:ws,RadialLinearScale:Os,TimeScale:Vs,TimeSeriesScale:Ws});return Yn.register(co,Hs,Eo,xs),Yn.helpers={...vn},Yn._adapters=Gn,Yn.Animation=mi,Yn.Animations=bi,Yn.animator=a,Yn.controllers=wn.controllers.items,Yn.DatasetController=Ai,Yn.Element=Oi,Yn.elements=Eo,Yn.Interaction=De,Yn.layouts=Xe,Yn.platforms=ci,Yn.Scale=ji,Yn.Ticks=Ei,Object.assign(Yn,co,Hs,Eo,xs,ci),Yn.Chart=Yn,"undefined"!=typeof window&&(window.Chart=Yn),Yn})); diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index cb78eabc6a..af7d6b7dc6 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -326,7 +326,7 @@ class PurchaseOrder(Order): return self.pending_line_items().count() == 0 @transaction.atomic - def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK): + def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None): """ Receive a line item (or partial line item) against this PO """ @@ -348,7 +348,8 @@ class PurchaseOrder(Order): location=location, quantity=quantity, purchase_order=self, - status=status + status=status, + purchase_price=purchase_price, ) stock.save() diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index bdf0407603..e6f82373c7 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -776,6 +776,7 @@ class PurchaseOrderReceive(AjaxUpdateView): line.receive_quantity, self.request.user, status=line.status_code, + purchase_price=line.purchase_price, ) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index c0b23ffbd7..04c046db5f 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -1,5 +1,6 @@ {% extends "modal_form.html" %} +{% load i18n %} {% block pre_form_content %}
@@ -77,6 +78,76 @@ Pricing information for:
{% endif %} + {% if price_history %} +

{% trans 'Stock Pricing' %}

+ {% if price_history|length > 1 %} + + + {% else %} +
+ {% trans 'No stock pricing history is available for this part.' %} +
+ {% endif %} + {% endif %} + {% if min_unit_buy_price or min_unit_bom_price %} {% else %}
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 0208636a48..e6426efd7e 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -2027,6 +2027,30 @@ class PartPricing(AjaxView): ctx['max_total_bom_price'] = max_bom_price ctx['max_unit_bom_price'] = max_bom_price / quantity + # Stock history + if part.total_stock > 1: + ret = [] + stock = part.stock_entries(include_variants=False, in_stock=True) + + for stock_item in stock: + if None in [stock_item.purchase_price, stock_item.quantity]: + continue + line = { + 'price': stock_item.purchase_price.amount, + 'qty': stock_item.quantity + } + if stock_item.supplier_part: + line['name'] = stock_item.supplier_part.pretty_name + + if stock_item.supplier_part.unit_pricing and stock_item.purchase_price: + line['price_diff'] = stock_item.supplier_part.unit_pricing - stock_item.purchase_price.amount + if stock_item.purchase_order: + + line['date'] = stock_item.purchase_order.issue_date.strftime('%d.%m.%Y') + ret.append(line) + + ctx['price_history'] = ret + return ctx def get(self, request, *args, **kwargs): diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index 2120d0ccfb..b90f025cc2 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -136,6 +136,7 @@ InvenTree + From 43422ca169938f11b83aa6036d2b58abb54ccc85 Mon Sep 17 00:00:00 2001 From: Matthias Mair <66015116+matmair@users.noreply.github.com> Date: Sun, 18 Apr 2021 01:42:52 +0200 Subject: [PATCH 002/300] squashing dev-branch (#14) * added action to auto-gen the translation base-file --- .github/workflows/translations.yml | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/translations.yml diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml new file mode 100644 index 0000000000..e0f38eb20a --- /dev/null +++ b/.github/workflows/translations.yml @@ -0,0 +1,63 @@ +name: Make Translation + +on: ["push", "pull_request"] +# on: +# push: +# branches: +# - master + + +jobs: + build: + + runs-on: ubuntu-latest + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + INVENTREE_DB_NAME: './test_db.sqlite' + INVENTREE_DB_ENGINE: django.db.backends.sqlite3 + INVENTREE_DEBUG: info + INVENTREE_MEDIA_ROOT: ./media + INVENTREE_STATIC_ROOT: ./static + + steps: + - uses: actions/checkout@v2 + - name: get current translations + run: | + git fetch + git checkout origin/l10_base -- `git ls-tree origin/l10_base -r --name-only | grep ".po"` + git reset + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y gettext + pip3 install invoke + invoke install + - name: Make Translations + run: | + cd InvenTree + python manage.py makemessages -e py -e html -e js + - name: stash changes + run: | + git stash + - name: Checkout tranlation-branch + uses: actions/checkout@v2.3.4 + with: + ref: l10_base + - name: Commit files + run: | + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git checkout stash -- . + git reset + git add "*.po" + git commit -m "generated translation base" + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: l10_base From cdea39def0e22c1ddc30bd06c615a6f00ddcf890 Mon Sep 17 00:00:00 2001 From: Matthias Mair <66015116+matmair@users.noreply.github.com> Date: Wed, 21 Apr 2021 11:16:05 +0200 Subject: [PATCH 003/300] use invoke for trans instead of commandline --- .github/workflows/translations.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index e0f38eb20a..b6579de008 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -39,8 +39,7 @@ jobs: invoke install - name: Make Translations run: | - cd InvenTree - python manage.py makemessages -e py -e html -e js + invoke translate - name: stash changes run: | git stash From decb56e3532276757021ab63b85784f1ed98fa52 Mon Sep 17 00:00:00 2001 From: Matthias Mair <66015116+matmair@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:27:25 +0200 Subject: [PATCH 004/300] updated reference for InvenTree/InvenTree won't work if there isn't a origin/l10 in the repo --- .github/workflows/translations.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index b6579de008..efce44fc14 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -25,7 +25,7 @@ jobs: - name: get current translations run: | git fetch - git checkout origin/l10_base -- `git ls-tree origin/l10_base -r --name-only | grep ".po"` + git checkout origin/l10 -- `git ls-tree origin/l10 -r --name-only | grep ".po"` git reset - name: Set up Python 3.7 uses: actions/setup-python@v1 @@ -46,7 +46,7 @@ jobs: - name: Checkout tranlation-branch uses: actions/checkout@v2.3.4 with: - ref: l10_base + ref: l10 - name: Commit files run: | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" @@ -54,9 +54,9 @@ jobs: git checkout stash -- . git reset git add "*.po" - git commit -m "generated translation base" + git commit -m "updated translation base" - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - branch: l10_base + branch: l10 From a0154067d24b74a967cb612b3d734c86b7418692 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Apr 2021 12:05:48 +0200 Subject: [PATCH 005/300] added setting -> default false --- InvenTree/common/models.py | 7 +++++++ InvenTree/part/settings.py | 8 ++++++++ InvenTree/part/templates/part/part_pricing.html | 5 ++++- InvenTree/part/test_part.py | 1 + InvenTree/part/views.py | 3 ++- InvenTree/templates/InvenTree/settings/part.html | 1 + 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index bc2ca4214b..7a2a91dea3 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -209,6 +209,13 @@ class InvenTreeSetting(models.Model): 'validator': bool, }, + 'PART_SHOW_GRAPH': { + 'name': _('Show Price History Graph'), + 'description': _('Display the price history graph in the part pricing view'), + 'default': False, + 'validator': bool, + }, + 'REPORT_DEBUG_MODE': { 'name': _('Debug Mode'), 'description': _('Generate reports in debug mode (HTML output)'), diff --git a/InvenTree/part/settings.py b/InvenTree/part/settings.py index 801b4dd2ec..a3913caa95 100644 --- a/InvenTree/part/settings.py +++ b/InvenTree/part/settings.py @@ -62,3 +62,11 @@ def part_trackable_default(): """ return InvenTreeSetting.get_setting('PART_TRACKABLE') + + +def part_show_graph(): + """ + Returns if the part pricing graph should be shown + """ + + return InvenTreeSetting.get_setting('PART_SHOW_GRAPH') diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index d0dc7f58c9..b07be7bdba 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -1,8 +1,11 @@ {% extends "modal_form.html" %} {% load i18n %} +{% load inventree_extras %} {% block pre_form_content %} +{% settings_value "PART_SHOW_GRAPH" as show_graph %} +
{% blocktrans %}Pricing information for:
{{part}}.{% endblocktrans %}
@@ -77,7 +80,7 @@ {% endif %} - {% if price_history %} + {% if show_graph and price_history %}

{% trans 'Stock Pricing' %}

{% if price_history|length > 1 %} diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 030d7faf4e..67fca7fc29 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -212,6 +212,7 @@ class PartSettingsTest(TestCase): self.assertFalse(part.settings.part_purchaseable_default()) self.assertFalse(part.settings.part_salable_default()) self.assertFalse(part.settings.part_trackable_default()) + self.assertFalse(part.settings.part_show_graph()) def test_initial(self): """ diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 8787a14b35..8113a52993 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -41,6 +41,7 @@ from common.models import InvenTreeSetting from company.models import SupplierPart import common.settings as inventree_settings +import part.settings as part_settings from . import forms as part_forms from .bom import MakeBomTemplate, BomUploadManager, ExportBom, IsValidBOMFormat @@ -2034,7 +2035,7 @@ class PartPricing(AjaxView): ctx['max_unit_bom_price'] = max_bom_price / quantity # Stock history - if part.total_stock > 1: + if part_settings.part_show_graph and part.total_stock > 1: ret = [] stock = part.stock_entries(include_variants=False, in_stock=True) diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html index 092d9c576c..a25fdbbcf6 100644 --- a/InvenTree/templates/InvenTree/settings/part.html +++ b/InvenTree/templates/InvenTree/settings/part.html @@ -21,6 +21,7 @@ {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_EDIT_IPN" %} {% include "InvenTree/settings/setting.html" with key="PART_SHOW_QUANTITY_IN_FORMS" icon="fa-hashtag" %} {% include "InvenTree/settings/setting.html" with key="PART_RECENT_COUNT" icon="fa-clock" %} + {% include "InvenTree/settings/setting.html" with key="PART_SHOW_GRAPH" icon="fa-chart-bar" %} {% include "InvenTree/settings/setting.html" with key="PART_TEMPLATE" icon="fa-clone" %} {% include "InvenTree/settings/setting.html" with key="PART_ASSEMBLY" icon="fa-tools" %} From 80d46fb3abc416bfc442faa2cbee6962fc2a5587 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Apr 2021 12:30:38 +0200 Subject: [PATCH 006/300] cleanup; using one currency --- .../part/templates/part/part_pricing.html | 165 +++++++++++------- InvenTree/part/views.py | 17 +- 2 files changed, 115 insertions(+), 67 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index b07be7bdba..9e29074e39 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -4,6 +4,7 @@ {% load inventree_extras %} {% block pre_form_content %} +{% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} {% settings_value "PART_SHOW_GRAPH" as show_graph %}
@@ -81,73 +82,111 @@ {% endif %} {% if show_graph and price_history %} -

{% trans 'Stock Pricing' %}

- {% if price_history|length > 1 %} - - - {% else %} -
- {% trans 'No stock pricing history is available for this part.' %} -
- {% endif %} + }); + + {% else %} +
+ {% trans 'No stock pricing history is available for this part.' %} +
+ {% endif %} {% endif %} {% if min_unit_buy_price or min_unit_bom_price %} diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 8113a52993..32bb8361b5 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -19,6 +19,7 @@ from django.forms import HiddenInput, CheckboxInput from django.conf import settings from moneyed import CURRENCIES +from djmoney.contrib.exchange.models import convert_money from PIL import Image @@ -2042,18 +2043,26 @@ class PartPricing(AjaxView): for stock_item in stock: if None in [stock_item.purchase_price, stock_item.quantity]: continue + + # convert purchase price to current currency - only one currency in the graph + price = convert_money(stock_item.purchase_price, inventree_settings.currency_code_default()) line = { - 'price': stock_item.purchase_price.amount, + 'price': price.amount, 'qty': stock_item.quantity } + # Supplier Part Name # TODO use in graph if stock_item.supplier_part: line['name'] = stock_item.supplier_part.pretty_name - if stock_item.supplier_part.unit_pricing and stock_item.purchase_price: - line['price_diff'] = stock_item.supplier_part.unit_pricing - stock_item.purchase_price.amount - if stock_item.purchase_order: + if stock_item.supplier_part.unit_pricing and price: + line['price_diff'] = price.amount - stock_item.supplier_part.unit_pricing + line['price_part'] = stock_item.supplier_part.unit_pricing + # set date for graph labels + if stock_item.purchase_order: line['date'] = stock_item.purchase_order.issue_date.strftime('%d.%m.%Y') + else: + line['date'] = stock_item.tracking_info.first().date.strftime('%d.%m.%Y') ret.append(line) ctx['price_history'] = ret From f7635fb1c01c7e29eafa029a4e24eb8dd1a55067 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Apr 2021 12:39:48 +0200 Subject: [PATCH 007/300] reording form --- .../part/templates/part/part_pricing.html | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index 9e29074e39..e046b5264c 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -2,11 +2,8 @@ {% load i18n %} {% load inventree_extras %} + {% block pre_form_content %} - -{% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} -{% settings_value "PART_SHOW_GRAPH" as show_graph %} -
{% blocktrans %}Pricing information for:
{{part}}.{% endblocktrans %}
@@ -81,6 +78,19 @@ {% endif %} + {% if min_unit_buy_price or min_unit_bom_price %} + {% else %} +
+ {% trans 'No pricing information is available for this part.' %} +
+ {% endif %} +
+{% endblock %} + +{% block post_form_content %} + {% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} + {% settings_value "PART_SHOW_GRAPH" as show_graph %} + {% if show_graph and price_history %}

{% trans 'Stock Pricing' %}

{% if price_history|length > 1 %} @@ -188,14 +198,4 @@
{% endif %} {% endif %} - -{% if min_unit_buy_price or min_unit_bom_price %} -{% else %} -
- {% trans 'No pricing information is available for this part.' %} -
-{% endif %} - -
- {% endblock %} \ No newline at end of file From 126c5ca3bfcfbeca8e27448b114aaa600b7cb974 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Apr 2021 12:48:42 +0200 Subject: [PATCH 008/300] typo --- InvenTree/part/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/settings.py b/InvenTree/part/settings.py index a3913caa95..671b7bf8f6 100644 --- a/InvenTree/part/settings.py +++ b/InvenTree/part/settings.py @@ -58,7 +58,7 @@ def part_salable_default(): def part_trackable_default(): """ - Returns the defualt value fro the 'trackable' field for a Part object + Returns the default value for the 'trackable' field for a Part object """ return InvenTreeSetting.get_setting('PART_TRACKABLE') From 294dd0525f8ca3c9ac85639134874fd72f0e173b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 22 Apr 2021 12:53:49 +0200 Subject: [PATCH 009/300] use spaces instead of tabs --- .../part/templates/part/category_parametric.html | 16 ++++++++-------- .../templates/InvenTree/settings/category.html | 6 +++--- .../templates/InvenTree/settings/stock.html | 2 +- .../templates/InvenTree/settings/theme.html | 12 ++++++------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/InvenTree/part/templates/part/category_parametric.html b/InvenTree/part/templates/part/category_parametric.html index 250530309e..881a292986 100644 --- a/InvenTree/part/templates/part/category_parametric.html +++ b/InvenTree/part/templates/part/category_parametric.html @@ -19,18 +19,18 @@ {% block js_ready %} {{ block.super }} - - /* Hide Button Toolbar */ - window.onload = function hideButtonToolbar() { - var toolbar = document.getElementById("button-toolbar"); - toolbar.style.display = "none"; - }; + + /* Hide Button Toolbar */ + window.onload = function hideButtonToolbar() { + var toolbar = document.getElementById("button-toolbar"); + toolbar.style.display = "none"; + }; loadParametricPartTable( "#parametric-part-table", { - headers: {{ headers|safe }}, - data: {{ parameters|safe }}, + headers: {{ headers|safe }}, + data: {{ parameters|safe }}, } ); diff --git a/InvenTree/templates/InvenTree/settings/category.html b/InvenTree/templates/InvenTree/settings/category.html index 07dd0df342..0e70d2c90e 100644 --- a/InvenTree/templates/InvenTree/settings/category.html +++ b/InvenTree/templates/InvenTree/settings/category.html @@ -44,7 +44,7 @@ }); {% if category %} - $("#param-table").inventreeTable({ + $("#param-table").inventreeTable({ url: "{% url 'api-part-category-parameters' pk=category.pk %}", queryParams: { ordering: 'name', @@ -66,7 +66,7 @@ field: 'default_value', title: '{% trans "Default Value" %}', sortable: 'true', - formatter: function(value, row, index, field) { + formatter: function(value, row, index, field) { var bEdit = ""; var bDel = ""; @@ -79,7 +79,7 @@ ] }); - $("#new-param").click(function() { + $("#new-param").click(function() { launchModalForm("{% url 'category-param-template-create' category.pk %}", { success: function() { $("#param-table").bootstrapTable('refresh'); diff --git a/InvenTree/templates/InvenTree/settings/stock.html b/InvenTree/templates/InvenTree/settings/stock.html index 7909e11a60..7cf7a94e0b 100644 --- a/InvenTree/templates/InvenTree/settings/stock.html +++ b/InvenTree/templates/InvenTree/settings/stock.html @@ -21,7 +21,7 @@ {% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" icon="fa-calendar" %} {% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" icon="fa-truck" %} {% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" icon="fa-tools" %} - {% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" icon="fa-users" %} + {% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" icon="fa-users" %} {% endblock %} diff --git a/InvenTree/templates/InvenTree/settings/theme.html b/InvenTree/templates/InvenTree/settings/theme.html index 413bb67dd3..d7b006d13c 100644 --- a/InvenTree/templates/InvenTree/settings/theme.html +++ b/InvenTree/templates/InvenTree/settings/theme.html @@ -25,12 +25,12 @@ {% if invalid_color_theme %} - + {% endif %} {% endblock %} From d6ef9ee212984f70f3574e900b8d67b44d6457d1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 22 Apr 2021 23:19:11 +1000 Subject: [PATCH 010/300] Adds some more translatable strings - Mostly just to check the workflow integration --- InvenTree/templates/about.html | 4 ++-- InvenTree/templates/navbar.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/templates/about.html b/InvenTree/templates/about.html index 3a650adba2..15ff588576 100644 --- a/InvenTree/templates/about.html +++ b/InvenTree/templates/about.html @@ -60,7 +60,7 @@ - {% trans "Get the App" %} + {% trans "Mobile App" %} https://inventree.readthedocs.io/en/latest/app/app @@ -74,7 +74,7 @@
diff --git a/InvenTree/templates/navbar.html b/InvenTree/templates/navbar.html index 55e0e06018..42124266d6 100644 --- a/InvenTree/templates/navbar.html +++ b/InvenTree/templates/navbar.html @@ -10,7 +10,7 @@ +
{% csrf_token %} @@ -33,4 +33,35 @@ {% endif %} + +
+
+

{% trans "Language" %}

+
+
+ + + +
+ {% csrf_token %} + +
+ +
+
+ +
+ +
+ + {% endblock %} From c5640fe6c6e439899c5594f55c4739bf946f2170 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 28 Apr 2021 14:37:11 +0200 Subject: [PATCH 049/300] renamed theme to appearance --- InvenTree/InvenTree/urls.py | 3 ++- InvenTree/InvenTree/views.py | 8 ++++---- .../InvenTree/settings/{theme.html => appearance.html} | 3 +-- InvenTree/templates/InvenTree/settings/tabs.html | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) rename InvenTree/templates/InvenTree/settings/{theme.html => appearance.html} (94%) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 003214cd02..c57e82addc 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -39,7 +39,7 @@ from rest_framework.documentation import include_docs_urls from .views import IndexView, SearchView, DatabaseStatsView from .views import SettingsView, EditUserView, SetPasswordView -from .views import ColorThemeSelectView, SettingCategorySelectView +from .views import AppearanceSelectView, SettingCategorySelectView from .views import DynamicJsView from common.views import SettingEdit @@ -79,6 +79,7 @@ apipatterns = [ settings_urls = [ url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'), + url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'), url(r'^i18n/?', include('django.conf.urls.i18n')), url(r'^global/?', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'), diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 5a080d7cdc..def4b34781 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -769,12 +769,12 @@ class SettingsView(TemplateView): return ctx -class ColorThemeSelectView(FormView): +class AppearanceSelectView(FormView): """ View for selecting a color theme """ form_class = ColorThemeSelectForm - success_url = reverse_lazy('settings-theme') - template_name = "InvenTree/settings/theme.html" + success_url = reverse_lazy('settings-appearance') + template_name = "InvenTree/settings/appearance.html" def get_user_theme(self): """ Get current user color theme """ @@ -788,7 +788,7 @@ class ColorThemeSelectView(FormView): def get_initial(self): """ Select current user color theme as initial choice """ - initial = super(ColorThemeSelectView, self).get_initial() + initial = super(AppearanceSelectView, self).get_initial() user_theme = self.get_user_theme() if user_theme: diff --git a/InvenTree/templates/InvenTree/settings/theme.html b/InvenTree/templates/InvenTree/settings/appearance.html similarity index 94% rename from InvenTree/templates/InvenTree/settings/theme.html rename to InvenTree/templates/InvenTree/settings/appearance.html index f0f9872774..e02af976ec 100644 --- a/InvenTree/templates/InvenTree/settings/theme.html +++ b/InvenTree/templates/InvenTree/settings/appearance.html @@ -18,7 +18,7 @@ -
+ {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} @@ -44,7 +44,6 @@
{% csrf_token %} -
+ + +{% endblock %} + +{% block js_ready %} +{{ block.super }} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 97903d81c1..9e25c2e870 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -17,6 +17,7 @@ purchase_order_detail_urls = [ url(r'^receive/', views.PurchaseOrderReceive.as_view(), name='po-receive'), url(r'^complete/', views.PurchaseOrderComplete.as_view(), name='po-complete'), + url(r'^upload/', views.PurchaseOrderUpload.as_view(), name='po-upload'), url(r'^export/', views.PurchaseOrderExport.as_view(), name='po-export'), url(r'^notes/', views.PurchaseOrderNotes.as_view(), name='po-notes'), diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 284a24fcf5..d221f7bc02 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -9,6 +9,7 @@ from django.db import transaction from django.shortcuts import get_object_or_404 from django.core.exceptions import ValidationError from django.urls import reverse +from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ from django.views.generic import DetailView, ListView, UpdateView from django.views.generic.edit import FormMixin @@ -27,6 +28,7 @@ from stock.models import StockItem, StockLocation from part.models import Part from common.models import InvenTreeSetting +from common.views import FileUploadWizardView from . import forms as order_forms @@ -564,6 +566,24 @@ class SalesOrderShip(AjaxUpdateView): return self.renderJsonResponse(request, form, data, context) +class PurchaseOrderUpload(FileUploadWizardView): + ''' Upload File Wizard View ''' + + template_name = "order/po_upload.html" + + def get_context_data(self, form, **kwargs): + context = super().get_context_data(form=form, **kwargs) + + order = get_object_or_404(PurchaseOrder, pk=self.kwargs['pk']) + + context.update({'order': order}) + + return context + + def done(self, form_list, **kwargs): + return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) + + class PurchaseOrderExport(AjaxView): """ File download for a purchase order diff --git a/requirements.txt b/requirements.txt index 3291574084..beaa30c4fe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,5 +32,6 @@ python-barcode[images]==0.13.1 # Barcode generator qrcode[pil]==6.1 # QR code generator django-q==1.3.4 # Background task scheduling gunicorn>=20.0.4 # Gunicorn web server +django-formtools==2.3 # Form wizard tools inventree # Install the latest version of the InvenTree API python library From 373898d43e777f1d33c1644b6b53498f54e57c1a Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 4 May 2021 10:28:00 -0400 Subject: [PATCH 061/300] Added step description and crispy form tag --- InvenTree/common/forms.py | 15 ---------- InvenTree/common/views.py | 29 ++++++++++++++----- InvenTree/order/forms.py | 15 ++++++++++ .../order/templates/order/po_upload.html | 15 ++++++---- InvenTree/order/views.py | 17 +++++++++-- 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index 0ca98ad76a..f4ff082019 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -23,18 +23,3 @@ class SettingEditForm(HelperForm): fields = [ 'value' ] - - -class UploadFile(forms.Form): - ''' Step 1 ''' - first_name = forms.CharField(max_length=100) - - -class MatchField(forms.Form): - ''' Step 2 ''' - last_name = forms.CharField(max_length=100) - - -class MatchPart(forms.Form): - ''' Step 3 ''' - age = forms.IntegerField() diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index f25760990e..056cbec32b 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -105,10 +105,25 @@ class SettingEdit(AjaxUpdateView): form.add_error('value', _('Supplied value must be a boolean')) -class FileUploadWizardView(SessionWizardView): - # file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'file_uploads')) - form_list = [ - forms.UploadFile, - forms.MatchField, - forms.MatchPart, - ] +class MultiStepFormView(SessionWizardView): + """ Setup basic methods of multi-step form + + form_list: list of forms + form_steps_description: description for each form + """ + + form_list = [] + form_steps_description = [] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + # Get description + try: + description = self.form_steps_description[int(self.steps.current)] + except IndexError: + description = '' + # Add description to form steps + context.update({'description': description}) + + return context + \ No newline at end of file diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 4c9caf3b53..b5b1aa2c96 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -284,3 +284,18 @@ class EditSalesOrderAllocationForm(HelperForm): 'line', 'item', 'quantity'] + + +class UploadFile(forms.Form): + ''' Step 1 ''' + first_name = forms.CharField(max_length=100) + + +class MatchField(forms.Form): + ''' Step 2 ''' + last_name = forms.CharField(max_length=100) + + +class MatchPart(forms.Form): + ''' Step 3 ''' + age = forms.IntegerField() \ No newline at end of file diff --git a/InvenTree/order/templates/order/po_upload.html b/InvenTree/order/templates/order/po_upload.html index b221800d3c..8563b70ff5 100644 --- a/InvenTree/order/templates/order/po_upload.html +++ b/InvenTree/order/templates/order/po_upload.html @@ -9,29 +9,32 @@ {% endblock %} {% block heading %} +{% trans "Upload File for Purchase Order" %} {{ wizard.form.media }} {% endblock %} {% block details %} -

Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}

+

{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }} +{% if description %}- {{ description }}{% endif %}

{% csrf_token %} +{% load crispy_forms_tags %} {{ wizard.management_form }} {% if wizard.form.forms %} {{ wizard.form.management_form }} {% for form in wizard.form.forms %} - {{ form }} + {% crispy form %} {% endfor %} {% else %} - {{ wizard.form }} + {% crispy wizard.form %} {% endif %}
{% if wizard.steps.prev %} - - + + {% endif %} - +
{% endblock %} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index d221f7bc02..92f5d54c33 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -28,7 +28,7 @@ from stock.models import StockItem, StockLocation from part.models import Part from common.models import InvenTreeSetting -from common.views import FileUploadWizardView +from common.views import MultiStepFormView from . import forms as order_forms @@ -566,10 +566,21 @@ class SalesOrderShip(AjaxUpdateView): return self.renderJsonResponse(request, form, data, context) -class PurchaseOrderUpload(FileUploadWizardView): - ''' Upload File Wizard View ''' +class PurchaseOrderUpload(MultiStepFormView): + ''' PurchaseOrder: Upload file and match to parts, using multi-Step form ''' + form_list = [ + order_forms.UploadFile, + order_forms.MatchField, + order_forms.MatchPart, + ] + form_steps_description = [ + _("Upload File"), + _("Select Fields"), + _("Select Parts"), + ] template_name = "order/po_upload.html" + # file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'file_uploads')) def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) From 7cdf0af04a721a695975808d982596190d00b4a5 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 4 May 2021 12:20:57 -0400 Subject: [PATCH 062/300] Added upload file step --- InvenTree/common/files.py | 184 ++++++++++++++++++ InvenTree/common/forms.py | 2 - InvenTree/common/views.py | 18 +- InvenTree/order/forms.py | 26 ++- .../order/templates/order/po_upload.html | 2 +- InvenTree/order/views.py | 20 +- 6 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 InvenTree/common/files.py diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py new file mode 100644 index 0000000000..1964e662e2 --- /dev/null +++ b/InvenTree/common/files.py @@ -0,0 +1,184 @@ +""" +Files management tools. +""" + +from rapidfuzz import fuzz +import tablib +import os + +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError + +# from company.models import ManufacturerPart, SupplierPart + + +class FileManager: + """ Class for managing an uploaded file """ + + name = '' + + # Fields which are absolutely necessary for valid upload + REQUIRED_HEADERS = [ + 'Quantity' + ] + + # Fields which are used for part matching (only one of them is needed) + PART_MATCH_HEADERS = [ + 'Part_Name', + 'Part_IPN', + 'Part_ID', + ] + + # Fields which would be helpful but are not required + OPTIONAL_HEADERS = [ + ] + + EDITABLE_HEADERS = [ + ] + + HEADERS = REQUIRED_HEADERS + PART_MATCH_HEADERS + OPTIONAL_HEADERS + + def __init__(self, file, name=None): + """ Initialize the FileManager class with a user-uploaded file object """ + + # Set name + if name: + self.name = name + + # Process initial file + self.process(file) + + def process(self, file): + """ Process file """ + + self.data = None + + ext = os.path.splitext(file.name)[-1].lower() + + if ext in ['.csv', '.tsv', ]: + # These file formats need string decoding + raw_data = file.read().decode('utf-8') + elif ext in ['.xls', '.xlsx']: + raw_data = file.read() + else: + raise ValidationError(_(f'Unsupported file format: {ext}')) + + try: + self.data = tablib.Dataset().load(raw_data) + except tablib.UnsupportedFormat: + raise ValidationError(_(f'Error reading {self.name} file (invalid format)')) + except tablib.core.InvalidDimensions: + raise ValidationError(_(f'Error reading {self.name} file (incorrect dimension)')) + + def guess_header(self, header, threshold=80): + """ Try to match a header (from the file) to a list of known headers + + Args: + header - Header name to look for + threshold - Match threshold for fuzzy search + """ + + # Try for an exact match + for h in self.HEADERS: + if h == header: + return h + + # Try for a case-insensitive match + for h in self.HEADERS: + if h.lower() == header.lower(): + return h + + # Try for a case-insensitive match with space replacement + for h in self.HEADERS: + if h.lower() == header.lower().replace(' ', '_'): + return h + + # Finally, look for a close match using fuzzy matching + matches = [] + + for h in self.HEADERS: + ratio = fuzz.partial_ratio(header, h) + if ratio > threshold: + matches.append({'header': h, 'match': ratio}) + + if len(matches) > 0: + matches = sorted(matches, key=lambda item: item['match'], reverse=True) + return matches[0]['header'] + + return None + + def columns(self): + """ Return a list of headers for the thingy """ + headers = [] + + for header in self.data.headers: + headers.append({ + 'name': header, + 'guess': self.guess_header(header) + }) + + return headers + + def col_count(self): + if self.data is None: + return 0 + + return len(self.data.headers) + + def row_count(self): + """ Return the number of rows in the file. """ + + if self.data is None: + return 0 + + return len(self.data) + + def rows(self): + """ Return a list of all rows """ + rows = [] + + for i in range(self.row_count()): + + data = [item for item in self.get_row_data(i)] + + # Is the row completely empty? Skip! + empty = True + + for idx, item in enumerate(data): + if len(str(item).strip()) > 0: + empty = False + + try: + # Excel import casts number-looking-items into floats, which is annoying + if item == int(item) and not str(item) == str(int(item)): + data[idx] = int(item) + except ValueError: + pass + + # Skip empty rows + if empty: + continue + + row = { + 'data': data, + 'index': i + } + + rows.append(row) + + return rows + + def get_row_data(self, index): + """ Retrieve row data at a particular index """ + if self.data is None or index >= len(self.data): + return None + + return self.data[index] + + def get_row_dict(self, index): + """ Retrieve a dict object representing the data row at a particular offset """ + + if self.data is None or index >= len(self.data): + return None + + return self.data.dict[index] diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index f4ff082019..84e44f3a31 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -5,8 +5,6 @@ Django forms for interacting with common objects # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django import forms - from InvenTree.forms import HelperForm from .models import InvenTreeSetting diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 056cbec32b..8220b00554 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -5,8 +5,12 @@ Django views for interacting with common models # -*- coding: utf-8 -*- from __future__ import unicode_literals +import os + from django.utils.translation import ugettext_lazy as _ from django.forms import CheckboxInput, Select +from django.conf import settings +from django.core.files.storage import FileSystemStorage from formtools.wizard.views import SessionWizardView @@ -106,7 +110,7 @@ class SettingEdit(AjaxUpdateView): class MultiStepFormView(SessionWizardView): - """ Setup basic methods of multi-step form + """ Setup basic methods of multi-step form form_list: list of forms form_steps_description: description for each form @@ -114,6 +118,17 @@ class MultiStepFormView(SessionWizardView): form_list = [] form_steps_description = [] + media_folder = '' + file_storage = FileSystemStorage(settings.MEDIA_ROOT) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if self.media_folder: + media_folder_abs = os.path.join(settings.MEDIA_ROOT, self.media_folder) + if not os.path.exists(media_folder_abs): + os.mkdir(media_folder_abs) + self.file_storage = FileSystemStorage(location=media_folder_abs) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -126,4 +141,3 @@ class MultiStepFormView(SessionWizardView): context.update({'description': description}) return context - \ No newline at end of file diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index b5b1aa2c96..5f6253217c 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -14,6 +14,8 @@ from InvenTree.forms import HelperForm from InvenTree.fields import RoundingDecimalFormField from InvenTree.fields import DatePickerFormField +from common.files import FileManager + import part.models from stock.models import StockLocation @@ -287,15 +289,29 @@ class EditSalesOrderAllocationForm(HelperForm): class UploadFile(forms.Form): - ''' Step 1 ''' - first_name = forms.CharField(max_length=100) + """ Step 1 """ + file = forms.FileField( + label=_('Order File'), + help_text=_('Select order file to upload'), + ) + + file_manager = None + + def clean_file(self): + file = self.cleaned_data['file'] + + # Create a FileManager object - will perform initial data validation + # (and raise a ValidationError if there is something wrong with the file) + self.file_manager = FileManager(file=file, name='order') + + return file class MatchField(forms.Form): - ''' Step 2 ''' + """ Step 2 """ last_name = forms.CharField(max_length=100) class MatchPart(forms.Form): - ''' Step 3 ''' - age = forms.IntegerField() \ No newline at end of file + """ Step 3 """ + age = forms.IntegerField() diff --git a/InvenTree/order/templates/order/po_upload.html b/InvenTree/order/templates/order/po_upload.html index 8563b70ff5..9650ee763d 100644 --- a/InvenTree/order/templates/order/po_upload.html +++ b/InvenTree/order/templates/order/po_upload.html @@ -17,7 +17,7 @@

{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }} {% if description %}- {{ description }}{% endif %}

-
{% csrf_token %} +{% csrf_token %} {% load crispy_forms_tags %} {{ wizard.management_form }} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 92f5d54c33..ec9a4a4742 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -580,7 +580,7 @@ class PurchaseOrderUpload(MultiStepFormView): _("Select Parts"), ] template_name = "order/po_upload.html" - # file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'file_uploads')) + media_folder = 'order_uploads/' def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -591,6 +591,24 @@ class PurchaseOrderUpload(MultiStepFormView): return context + def get_form_step_data(self, form): + # print(f'{self.steps.current=}\n{form.data=}') + return form.data + + def get_form_step_files(self, form): + # Check if user completed file upload + if self.steps.current == '0': + # Extract columns and rows from FileManager + self.extractDataFromFile(form.file_manager) + + return form.files + + def extractDataFromFile(self, file_manager): + """ Read data from the file """ + + self.columns = file_manager.columns() + self.rows = file_manager.rows() + def done(self, form_list, **kwargs): return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) From 64fb492b9711977f325bd10f7c036dcd967af166 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 4 May 2021 14:45:52 -0400 Subject: [PATCH 063/300] Added match parts step, need to process fields data --- InvenTree/common/files.py | 52 ++++++-- InvenTree/common/views.py | 25 +++- InvenTree/order/forms.py | 4 +- .../order/order_wizard/match_fields.html | 89 ++++++++++++++ .../order/order_wizard/match_parts.html | 112 ++++++++++++++++++ .../order/{ => order_wizard}/po_upload.html | 16 ++- InvenTree/order/views.py | 64 +++++++--- 7 files changed, 326 insertions(+), 36 deletions(-) create mode 100644 InvenTree/order/templates/order/order_wizard/match_fields.html create mode 100644 InvenTree/order/templates/order/order_wizard/match_parts.html rename InvenTree/order/templates/order/{ => order_wizard}/po_upload.html (80%) diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py index 1964e662e2..ab73ec4f1e 100644 --- a/InvenTree/common/files.py +++ b/InvenTree/common/files.py @@ -18,25 +18,17 @@ class FileManager: name = '' # Fields which are absolutely necessary for valid upload - REQUIRED_HEADERS = [ - 'Quantity' - ] + REQUIRED_HEADERS = [] # Fields which are used for part matching (only one of them is needed) - PART_MATCH_HEADERS = [ - 'Part_Name', - 'Part_IPN', - 'Part_ID', - ] + PART_MATCH_HEADERS = [] # Fields which would be helpful but are not required - OPTIONAL_HEADERS = [ - ] + OPTIONAL_HEADERS = [] - EDITABLE_HEADERS = [ - ] + EDITABLE_HEADERS = [] - HEADERS = REQUIRED_HEADERS + PART_MATCH_HEADERS + OPTIONAL_HEADERS + HEADERS = [] def __init__(self, file, name=None): """ Initialize the FileManager class with a user-uploaded file object """ @@ -48,6 +40,9 @@ class FileManager: # Process initial file self.process(file) + # Update headers + self.update_headers() + def process(self, file): """ Process file """ @@ -69,6 +64,37 @@ class FileManager: raise ValidationError(_(f'Error reading {self.name} file (invalid format)')) except tablib.core.InvalidDimensions: raise ValidationError(_(f'Error reading {self.name} file (incorrect dimension)')) + + def update_headers(self): + """ Update headers """ + + self.HEADERS = self.REQUIRED_HEADERS + self.PART_MATCH_HEADERS + self.OPTIONAL_HEADERS + + def setup(self): + """ Setup headers depending on the file name """ + + if not self.name: + return False + + if self.name == 'order': + self.REQUIRED_HEADERS = [ + 'Quantity', + ] + + self.PART_MATCH_HEADERS = [ + 'Manufacturer_MPN', + 'Supplier_SKU', + ] + + self.OPTIONAL_HEADERS = [ + 'Unit_Price', + 'Extended_Price', + ] + + # Update headers + self.update_headers() + + return True def guess_header(self, header, threshold=80): """ Try to match a header (from the file) to a list of known headers diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 8220b00554..af3f7fea94 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -117,22 +117,45 @@ class MultiStepFormView(SessionWizardView): """ form_list = [] + form_steps_template = [] form_steps_description = [] + file_manager = None media_folder = '' file_storage = FileSystemStorage(settings.MEDIA_ROOT) def __init__(self, *args, **kwargs): + """ Override init method to set media folder """ super().__init__(*args, **kwargs) + self.process_media_folder() + + def process_media_folder(self): + """ Process media folder """ + if self.media_folder: media_folder_abs = os.path.join(settings.MEDIA_ROOT, self.media_folder) if not os.path.exists(media_folder_abs): os.mkdir(media_folder_abs) self.file_storage = FileSystemStorage(location=media_folder_abs) + def get_template_names(self): + """ Select template """ + + try: + # Get template + template = self.form_steps_template[int(self.steps.current)] + except IndexError: + return self.template_name + + return template + def get_context_data(self, **kwargs): + """ Update context data """ + + # Retrieve current context context = super().get_context_data(**kwargs) - # Get description + + # Get form description try: description = self.form_steps_description[int(self.steps.current)] except IndexError: diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 5f6253217c..b1e5745937 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -309,9 +309,9 @@ class UploadFile(forms.Form): class MatchField(forms.Form): """ Step 2 """ - last_name = forms.CharField(max_length=100) + pass class MatchPart(forms.Form): """ Step 3 """ - age = forms.IntegerField() + pass diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html new file mode 100644 index 0000000000..818f986850 --- /dev/null +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -0,0 +1,89 @@ +{% extends "order/order_wizard/po_upload.html" %} +{% load inventree_extras %} +{% load i18n %} +{% load static %} + +{% block form %} + +{% if missing_columns and missing_columns|length > 0 %} + +{% endif %} + + + {% csrf_token %} + {% load crispy_forms_tags %} + {{ wizard.management_form }} + + {% if wizard.steps.prev %} + + {% endif %} + + +
+ + + + + {% for col in columns %} + + {% endfor %} + + + + + + + {% for col in columns %} + + {% endfor %} + + {% for row in rows %} + {% with forloop.counter as row_index %} + + + + {% for item in row.data %} + + {% endfor %} + + {% endwith %} + {% endfor %} + +
{% trans "File Fields" %} +
+ + {{ col.name }} + +
+
{% trans "Match Fields" %} + + {% if col.duplicate %} +

{% trans "Duplicate column selection" %}

+ {% endif %} +
+ + {{ row_index }} + + {{ item }} +
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html new file mode 100644 index 0000000000..a1c5103e9e --- /dev/null +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -0,0 +1,112 @@ +{% extends "order/order_wizard/po_upload.html" %} +{% load inventree_extras %} +{% load i18n %} +{% load static %} + +{% block form %} + +{% if form_errors %} + +{% endif %} + +
+ {% csrf_token %} + {% load crispy_forms_tags %} + {{ wizard.management_form }} + + {% if wizard.steps.prev %} + + {% endif %} + + {% csrf_token %} + + + + + + + + + {% for col in bom_columns %} + + {% endfor %} + + + + {% for row in bom_rows %} + + + + + + {% for item in row.data %} + + {% endfor %} + + {% endfor %} + +
{% trans "Row" %}{% trans "Select Part" %} + + + {% if col.guess %} + {{ col.guess }} + {% else %} + {{ col.name }} + {% endif %} +
+ + {% add row.index 1 %} + + + {% if row.errors.part %} +

{{ row.errors.part }}

+ {% endif %} +
+ {% if item.column.guess == 'Part' %} + {{ item.cell }} + {% if row.errors.part %} +

{{ row.errors.part }}

+ {% endif %} + {% elif item.column.guess == 'Quantity' %} + + {% if row.errors.quantity %} +

{{ row.errors.quantity }}

+ {% endif %} + {% elif item.column.guess == 'Reference' %} + + {% elif item.column.guess == 'Note' %} + + {% elif item.column.guess == 'Overage' %} + + {% else %} + {{ item.cell }} + {% endif %} + +
+ +
+ +{% endblock %} + +{% block js_ready %} +{{ block.super }} + +$('.bomselect').select2({ + dropdownAutoWidth: true, + matcher: partialMatcher, +}); + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/po_upload.html b/InvenTree/order/templates/order/order_wizard/po_upload.html similarity index 80% rename from InvenTree/order/templates/order/po_upload.html rename to InvenTree/order/templates/order/order_wizard/po_upload.html index 9650ee763d..2c7c49b662 100644 --- a/InvenTree/order/templates/order/po_upload.html +++ b/InvenTree/order/templates/order/order_wizard/po_upload.html @@ -1,5 +1,4 @@ {% extends "order/order_base.html" %} - {% load inventree_extras %} {% load i18n %} {% load static %} @@ -17,7 +16,11 @@

{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }} {% if description %}- {{ description }}{% endif %}

-
{% csrf_token %} + +{% block form %} + + +{% csrf_token %} {% load crispy_forms_tags %} {{ wizard.management_form }} @@ -29,15 +32,16 @@ {% else %} {% crispy wizard.form %} {% endif %} -
-{% if wizard.steps.prev %} +{% if wizard.steps.prev %} {% endif %} - +
+ -{% endblock %} +{% endblock form %} +{% endblock details %} {% block js_ready %} {{ block.super }} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index ec9a4a4742..f9eb94eaa2 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -567,21 +567,30 @@ class SalesOrderShip(AjaxUpdateView): class PurchaseOrderUpload(MultiStepFormView): - ''' PurchaseOrder: Upload file and match to parts, using multi-Step form ''' + ''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) ''' form_list = [ order_forms.UploadFile, order_forms.MatchField, order_forms.MatchPart, ] + form_steps_template = [ + 'order/order_wizard/po_upload.html', + 'order/order_wizard/match_fields.html', + 'order/order_wizard/match_parts.html', + ] form_steps_description = [ _("Upload File"), - _("Select Fields"), - _("Select Parts"), + _("Match Fields"), + _("Match Parts"), ] - template_name = "order/po_upload.html" media_folder = 'order_uploads/' + # Used for data table + headers = None + rows = None + columns = None + def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -589,25 +598,52 @@ class PurchaseOrderUpload(MultiStepFormView): context.update({'order': order}) + if self.headers: + context.update({'headers': self.headers}) + # print(f'{self.headers}') + if self.columns: + context.update({'columns': self.columns}) + # print(f'{self.columns}') + if self.rows: + context.update({'rows': self.rows}) + # print(f'{self.rows}') + return context - def get_form_step_data(self, form): - # print(f'{self.steps.current=}\n{form.data=}') - return form.data + def process_step(self, form): + print(f'{self.steps.current=} | {form.data}') + return self.get_form_step_data(form) + + # def get_all_cleaned_data(self): + # cleaned_data = super().get_all_cleaned_data() + # print(f'{self.steps.current=} | {cleaned_data}') + # return cleaned_data + + # def get_form_step_data(self, form): + # print(f'{self.steps.current=} | {form.data}') + # return form.data def get_form_step_files(self, form): # Check if user completed file upload if self.steps.current == '0': - # Extract columns and rows from FileManager - self.extractDataFromFile(form.file_manager) + # Retrieve FileManager instance from form + self.file_manager = form.file_manager + # Setup FileManager for order upload + setup_valid = self.file_manager.setup() + if setup_valid: + # Set headers + self.headers = self.file_manager.HEADERS + # Set columns and rows + self.columns = self.file_manager.columns() + self.rows = self.file_manager.rows() return form.files - def extractDataFromFile(self, file_manager): - """ Read data from the file """ - - self.columns = file_manager.columns() - self.rows = file_manager.rows() + def post(self, request, *args, **kwargs): + """ Perform the various 'POST' requests required. + """ + print('Posting!') + return super().post(*args, **kwargs) def done(self, form_list, **kwargs): return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) From 55cdeef30ea7a659a0943e2731a87618322a9333 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 21:33:00 +0200 Subject: [PATCH 064/300] adds price-calc to purchase order Fixes #1513 --- InvenTree/order/models.py | 18 +++++++++++++----- InvenTree/order/views.py | 14 +++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index ea70c3b56a..d3b09dec1e 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -223,7 +223,7 @@ class PurchaseOrder(Order): return reverse('po-detail', kwargs={'pk': self.id}) @transaction.atomic - def add_line_item(self, supplier_part, quantity, group=True, reference=''): + def add_line_item(self, supplier_part, quantity, group=True, reference='', purchase_price=None): """ Add a new line item to this purchase order. This function will check that: @@ -254,7 +254,12 @@ class PurchaseOrder(Order): if matches.count() > 0: line = matches.first() - line.quantity += quantity + # update quantity and price + quantity_new = line.quantity + quantity + line.quantity = quantity_new + supplier_price = supplier_part.get_price(quantity_new) + if line.purchase_price and supplier_price: + line.purchase_price = supplier_price / quantity_new line.save() return @@ -263,7 +268,9 @@ class PurchaseOrder(Order): order=self, part=supplier_part, quantity=quantity, - reference=reference) + reference=reference, + purchase_price=purchase_price, + ) line.save() @@ -329,7 +336,7 @@ class PurchaseOrder(Order): return self.pending_line_items().count() == 0 @transaction.atomic - def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK): + def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None): """ Receive a line item (or partial line item) against this PO """ @@ -353,7 +360,8 @@ class PurchaseOrder(Order): location=location, quantity=quantity, purchase_order=self, - status=status + status=status, + purchase_price=purchase_price, ) stock.save() diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 284a24fcf5..c62a3816d5 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -776,6 +776,7 @@ class PurchaseOrderReceive(AjaxUpdateView): line.receive_quantity, self.request.user, status=line.status_code, + purchase_price=line.purchase_price, ) @@ -996,6 +997,14 @@ class OrderParts(AjaxView): part.order_supplier = supplier_part.id if supplier_part else None part.order_quantity = quantity + # set supplier-price + if supplier_part: + supplier_price = supplier_part.get_price(quantity) + if supplier_price: + part.purchase_price = supplier_price / quantity + if not hasattr(part, 'purchase_price'): + part.purchase_price = None + self.parts.append(part) if supplier_part is None: @@ -1095,7 +1104,10 @@ class OrderParts(AjaxView): sp=item.order_supplier)) continue - order.add_line_item(supplier_part, quantity) + # get purchase price + purchase_price = item.purchase_price + + order.add_line_item(supplier_part, quantity, purchase_price=purchase_price) class POLineItemCreate(AjaxCreateView): From 1614c6e08af3fdbd61e26448b8bc9c39516dea5c Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 21:51:42 +0200 Subject: [PATCH 065/300] Add in sale price model --- InvenTree/order/forms.py | 1 + .../migrations/0045_auto_20210504_1946.py | 24 +++++++++++++++++++ InvenTree/order/models.py | 10 ++++++++ InvenTree/order/serializers.py | 4 ++++ tasks.py | 2 +- 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 InvenTree/order/migrations/0045_auto_20210504_1946.py diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 4c9caf3b53..8536c71ef5 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -211,6 +211,7 @@ class EditSalesOrderLineItemForm(HelperForm): 'part', 'quantity', 'reference', + 'sale_price', 'notes' ] diff --git a/InvenTree/order/migrations/0045_auto_20210504_1946.py b/InvenTree/order/migrations/0045_auto_20210504_1946.py new file mode 100644 index 0000000000..a8d9469dc7 --- /dev/null +++ b/InvenTree/order/migrations/0045_auto_20210504_1946.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2 on 2021-05-04 19:46 + +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0044_auto_20210404_2016'), + ] + + operations = [ + migrations.AddField( + model_name='salesorderlineitem', + name='sale_price', + field=djmoney.models.fields.MoneyField(blank=True, decimal_places=4, default_currency='USD', help_text='Unit sale price', max_digits=19, null=True, verbose_name='Sale Price'), + ), + migrations.AddField( + model_name='salesorderlineitem', + name='sale_price_currency', + field=djmoney.models.fields.CurrencyField(choices=[('AUD', 'Australian Dollar'), ('GBP', 'British Pound'), ('CAD', 'Canadian Dollar'), ('EUR', 'Euro'), ('JPY', 'Japanese Yen'), ('NZD', 'New Zealand Dollar'), ('USD', 'US Dollar')], default='USD', editable=False, max_length=3), + ), + ] diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index ea70c3b56a..f0df4a7ff1 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -664,12 +664,22 @@ class SalesOrderLineItem(OrderLineItem): Attributes: order: Link to the SalesOrder that this line item belongs to part: Link to a Part object (may be null) + sale_price: The unit sale price for this OrderLineItem """ order = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='lines', verbose_name=_('Order'), help_text=_('Sales Order')) part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, verbose_name=_('Part'), help_text=_('Part'), limit_choices_to={'salable': True}) + sale_price = MoneyField( + max_digits=19, + decimal_places=4, + default_currency='USD', + null=True, blank=True, + verbose_name=_('Sale Price'), + help_text=_('Unit sale price'), + ) + class Meta: unique_together = [ ] diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index a04798c303..2f4545fc30 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -278,6 +278,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer): quantity = serializers.FloatField() allocated = serializers.FloatField(source='allocated_quantity', read_only=True) fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True) + sale_price_string = serializers.CharField(source='sale_price', read_only=True) class Meta: model = SalesOrderLineItem @@ -294,6 +295,9 @@ class SOLineItemSerializer(InvenTreeModelSerializer): 'order_detail', 'part', 'part_detail', + 'sale_price', + 'sale_price_currency', + 'sale_price_string', ] diff --git a/tasks.py b/tasks.py index 3065d97243..6eed4c488e 100644 --- a/tasks.py +++ b/tasks.py @@ -65,7 +65,7 @@ def manage(c, cmd, pty=False): cmd - django command to run """ - c.run('cd {path} && python3 manage.py {cmd}'.format( + c.run('cd "{path}" && python3 manage.py {cmd}'.format( path=managePyDir(), cmd=cmd ), pty=pty) From 294e86cc38ca05e7943a4806c448f13d1f60323f Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 21:56:25 +0200 Subject: [PATCH 066/300] Add in sale price model --- InvenTree/order/forms.py | 1 + .../migrations/0045_auto_20210504_1946.py | 24 +++++++++++++++++++ InvenTree/order/models.py | 10 ++++++++ InvenTree/order/serializers.py | 4 ++++ 4 files changed, 39 insertions(+) create mode 100644 InvenTree/order/migrations/0045_auto_20210504_1946.py diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 4c9caf3b53..8536c71ef5 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -211,6 +211,7 @@ class EditSalesOrderLineItemForm(HelperForm): 'part', 'quantity', 'reference', + 'sale_price', 'notes' ] diff --git a/InvenTree/order/migrations/0045_auto_20210504_1946.py b/InvenTree/order/migrations/0045_auto_20210504_1946.py new file mode 100644 index 0000000000..a8d9469dc7 --- /dev/null +++ b/InvenTree/order/migrations/0045_auto_20210504_1946.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2 on 2021-05-04 19:46 + +from django.db import migrations +import djmoney.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0044_auto_20210404_2016'), + ] + + operations = [ + migrations.AddField( + model_name='salesorderlineitem', + name='sale_price', + field=djmoney.models.fields.MoneyField(blank=True, decimal_places=4, default_currency='USD', help_text='Unit sale price', max_digits=19, null=True, verbose_name='Sale Price'), + ), + migrations.AddField( + model_name='salesorderlineitem', + name='sale_price_currency', + field=djmoney.models.fields.CurrencyField(choices=[('AUD', 'Australian Dollar'), ('GBP', 'British Pound'), ('CAD', 'Canadian Dollar'), ('EUR', 'Euro'), ('JPY', 'Japanese Yen'), ('NZD', 'New Zealand Dollar'), ('USD', 'US Dollar')], default='USD', editable=False, max_length=3), + ), + ] diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index ea70c3b56a..f0df4a7ff1 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -664,12 +664,22 @@ class SalesOrderLineItem(OrderLineItem): Attributes: order: Link to the SalesOrder that this line item belongs to part: Link to a Part object (may be null) + sale_price: The unit sale price for this OrderLineItem """ order = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='lines', verbose_name=_('Order'), help_text=_('Sales Order')) part = models.ForeignKey('part.Part', on_delete=models.SET_NULL, related_name='sales_order_line_items', null=True, verbose_name=_('Part'), help_text=_('Part'), limit_choices_to={'salable': True}) + sale_price = MoneyField( + max_digits=19, + decimal_places=4, + default_currency='USD', + null=True, blank=True, + verbose_name=_('Sale Price'), + help_text=_('Unit sale price'), + ) + class Meta: unique_together = [ ] diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index a04798c303..2f4545fc30 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -278,6 +278,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer): quantity = serializers.FloatField() allocated = serializers.FloatField(source='allocated_quantity', read_only=True) fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True) + sale_price_string = serializers.CharField(source='sale_price', read_only=True) class Meta: model = SalesOrderLineItem @@ -294,6 +295,9 @@ class SOLineItemSerializer(InvenTreeModelSerializer): 'order_detail', 'part', 'part_detail', + 'sale_price', + 'sale_price_currency', + 'sale_price_string', ] From 28a67828e3ff88824eae97691865bf3d10f7e76d Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 22:04:05 +0200 Subject: [PATCH 067/300] [BUG] invoke: too many arguments Fixes #1543 --- tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index 3065d97243..6eed4c488e 100644 --- a/tasks.py +++ b/tasks.py @@ -65,7 +65,7 @@ def manage(c, cmd, pty=False): cmd - django command to run """ - c.run('cd {path} && python3 manage.py {cmd}'.format( + c.run('cd "{path}" && python3 manage.py {cmd}'.format( path=managePyDir(), cmd=cmd ), pty=pty) From 7fa235282bb3ff91eddea2e6c8350e6dad649861 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 22:50:04 +0200 Subject: [PATCH 068/300] sale price in ui --- InvenTree/order/templates/order/sales_order_detail.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 392a236931..e611ebc9e1 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -223,6 +223,14 @@ $("#so-lines-table").inventreeTable({ field: 'quantity', title: '{% trans "Quantity" %}', }, + { + sortable: true, + field: 'sale_price', + title: '{% trans "Unit Price" %}', + formatter: function(value, row) { + return row.sale_price_string || row.sale_price; + } + }, { field: 'allocated', {% if order.status == SalesOrderStatus.PENDING %} From b4342d6203a8c9ee6e0393570c5d2eef3111cd8b Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 4 May 2021 17:35:27 -0400 Subject: [PATCH 069/300] Fixed templates, not sure why can't keep FileManager across forms... and also need to save form data --- InvenTree/common/views.py | 4 +- InvenTree/order/forms.py | 6 +- .../order/order_wizard/match_fields.html | 125 +++++------ .../order/order_wizard/match_parts.html | 21 +- .../order/order_wizard/po_upload.html | 29 +-- InvenTree/order/views.py | 210 ++++++++++++++++-- 6 files changed, 275 insertions(+), 120 deletions(-) diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index af3f7fea94..2abe53d380 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -143,7 +143,7 @@ class MultiStepFormView(SessionWizardView): try: # Get template - template = self.form_steps_template[int(self.steps.current)] + template = self.form_steps_template[self.steps.index] except IndexError: return self.template_name @@ -157,7 +157,7 @@ class MultiStepFormView(SessionWizardView): # Get form description try: - description = self.form_steps_description[int(self.steps.current)] + description = self.form_steps_description[self.steps.index] except IndexError: description = '' # Add description to form steps diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index b1e5745937..858679ffdf 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -295,16 +295,14 @@ class UploadFile(forms.Form): help_text=_('Select order file to upload'), ) - file_manager = None - def clean_file(self): file = self.cleaned_data['file'] # Create a FileManager object - will perform initial data validation # (and raise a ValidationError if there is something wrong with the file) - self.file_manager = FileManager(file=file, name='order') + file_manager = FileManager(file=file, name='order') - return file + return file_manager class MatchField(forms.Form): diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index 818f986850..1ac1f30997 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -3,8 +3,7 @@ {% load i18n %} {% load static %} -{% block form %} - +{% block form_alert %} {% if missing_columns and missing_columns|length > 0 %} {% endif %} +{% endblock form_alert %} -
- {% csrf_token %} - {% load crispy_forms_tags %} - {{ wizard.management_form }} - +{% block form_buttons_top %} {% if wizard.steps.prev %} {% endif %} +{% endblock form_buttons_top %} - - - - - - {% for col in columns %} - - {% endfor %} - - - - - - - {% for col in columns %} - - {% endfor %} - - {% for row in rows %} - {% with forloop.counter as row_index %} - - + + + + {% for col in columns %} + - {% for item in row.data %} - - {% endfor %} - - {% endwith %} + + {% endfor %} - -
{% trans "File Fields" %} -
- - {{ col.name }} - -
-
{% trans "Match Fields" %} - - {% if col.duplicate %} -

{% trans "Duplicate column selection" %}

- {% endif %} -
-
{% trans "File Fields" %} +
+ + {{ col.name }} + - -
{{ row_index }} - - {{ item }} -
+ + + + + + {% trans "Match Fields" %} + {% for col in columns %} + + + {% if col.duplicate %} +

{% trans "Duplicate column selection" %}

+ {% endif %} + + {% endfor %} + + {% for row in rows %} + {% with forloop.counter as row_index %} + + + + + {{ row_index }} + {% for item in row.data %} + + + {{ item }} + + {% endfor %} + + {% endwith %} + {% endfor %} + +{% endblock form_content %} -
- -{% endblock %} \ No newline at end of file +{% block form_buttons_bottom %} +{% endblock form_buttons_bottom %} \ No newline at end of file diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index a1c5103e9e..735d847b87 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -3,26 +3,22 @@ {% load i18n %} {% load static %} -{% block form %} - +{% block form_alert %} {% if form_errors %} {% endif %} +{% endblock form_alert %} -
- {% csrf_token %} - {% load crispy_forms_tags %} - {{ wizard.management_form }} - +{% block form_buttons_top %} {% if wizard.steps.prev %} {% endif %} - {% csrf_token %} +{% endblock form_buttons_top %} - +{% block form_content %} @@ -95,11 +91,10 @@ {% endfor %} -
+{% endblock form_content %} -
- -{% endblock %} +{% block form_buttons_bottom %} +{% endblock form_buttons_bottom %} {% block js_ready %} {{ block.super }} diff --git a/InvenTree/order/templates/order/order_wizard/po_upload.html b/InvenTree/order/templates/order/order_wizard/po_upload.html index 2c7c49b662..129570417b 100644 --- a/InvenTree/order/templates/order/order_wizard/po_upload.html +++ b/InvenTree/order/templates/order/order_wizard/po_upload.html @@ -17,30 +17,31 @@

{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }} {% if description %}- {{ description }}{% endif %}

-{% block form %} +{% block form_alert %} +{% endblock form_alert %} -
+ {% csrf_token %} - {% load crispy_forms_tags %} -{{ wizard.management_form }} -{% if wizard.form.forms %} - {{ wizard.form.management_form }} - {% for form in wizard.form.forms %} - {% crispy form %} - {% endfor %} -{% else %} - {% crispy wizard.form %} -{% endif %} +{% block form_buttons_top %} +{% endblock form_buttons_top %} + +
+{{ wizard.management_form }} +{% block form_content %} +{% crispy wizard.form %} +{% endblock form_content %} +
+ +{% block form_buttons_bottom %} {% if wizard.steps.prev %} {% endif %}
- +{% endblock form_buttons_bottom %} -{% endblock form %} {% endblock details %} {% block js_ready %} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index f9eb94eaa2..ee11609b35 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -570,9 +570,9 @@ class PurchaseOrderUpload(MultiStepFormView): ''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) ''' form_list = [ - order_forms.UploadFile, - order_forms.MatchField, - order_forms.MatchPart, + ('upload', order_forms.UploadFile), + ('fields', order_forms.MatchField), + ('parts', order_forms.MatchPart), ] form_steps_template = [ 'order/order_wizard/po_upload.html', @@ -608,26 +608,152 @@ class PurchaseOrderUpload(MultiStepFormView): context.update({'rows': self.rows}) # print(f'{self.rows}') + print(f'{context=}') return context - def process_step(self, form): - print(f'{self.steps.current=} | {form.data}') - return self.get_form_step_data(form) + def getTableDataFromForm(self, form_data): + """ Extract table cell data from form data. + These data are used to maintain state between sessions. - # def get_all_cleaned_data(self): - # cleaned_data = super().get_all_cleaned_data() - # print(f'{self.steps.current=} | {cleaned_data}') - # return cleaned_data + Table data keys are as follows: - # def get_form_step_data(self, form): - # print(f'{self.steps.current=} | {form.data}') - # return form.data + col_name_ - Column name at idx as provided in the uploaded file + col_guess_ - Column guess at idx as selected + row__col - Cell data as provided in the uploaded file + + """ + + if not self.file_manager: + print('Lost file manager...') + return + + # Map the columns + self.column_names = {} + self.column_selections = {} + + self.row_data = {} + + for item in form_data: + value = form_data[item] + + # Column names as passed as col_name_ where idx is an integer + + # Extract the column names + if item.startswith('col_name_'): + try: + col_id = int(item.replace('col_name_', '')) + except ValueError: + continue + col_name = value + + self.column_names[col_id] = col_name + + # Extract the column selections (in the 'select fields' view) + if item.startswith('col_guess_'): + + try: + col_id = int(item.replace('col_guess_', '')) + except ValueError: + continue + + col_name = value + + self.column_selections[col_id] = value + + # Extract the row data + if item.startswith('row_'): + # Item should be of the format row__col_ + s = item.split('_') + + if len(s) < 4: + continue + + # Ignore row/col IDs which are not correct numeric values + try: + row_id = int(s[1]) + col_id = int(s[3]) + except ValueError: + continue + + if row_id not in self.row_data: + self.row_data[row_id] = {} + + self.row_data[row_id][col_id] = value + + self.col_ids = sorted(self.column_names.keys()) + + # Re-construct the data table + self.rows = [] + + for row_idx in sorted(self.row_data.keys()): + row = self.row_data[row_idx] + items = [] + + for col_idx in sorted(row.keys()): + + value = row[col_idx] + items.append(value) + + self.rows.append({ + 'index': row_idx, + 'data': items, + 'errors': {}, + }) + + # Construct the column data + self.columns = [] + + # Track any duplicate column selections + self.duplicates = False + + for col in self.col_ids: + + if col in self.column_selections: + guess = self.column_selections[col] + else: + guess = None + + header = ({ + 'name': self.column_names[col], + 'guess': guess + }) + + if guess: + n = list(self.column_selections.values()).count(self.column_selections[col]) + if n > 1: + header['duplicate'] = True + self.duplicates = True + + self.columns.append(header) + + # Are there any missing columns? + self.missing_columns = [] + + # Check that all required fields are present + for col in self.file_manager.REQUIRED_HEADERS: + if col not in self.column_selections.values(): + self.missing_columns.append(col) + + # Check that at least one of the part match field is present + part_match_found = False + for col in self.file_manager.PART_MATCH_HEADERS: + if col in self.column_selections.values(): + part_match_found = True + break + + # If not, notify user + if not part_match_found: + for col in self.file_manager.PART_MATCH_HEADERS: + self.missing_columns.append(col) + + def handleFileUpload(self, form): + """ Process file upload and setup fields form """ - def get_form_step_files(self, form): # Check if user completed file upload - if self.steps.current == '0': - # Retrieve FileManager instance from form - self.file_manager = form.file_manager + if self.steps.current == 'upload': + # Copy FileManager instance from form + self.file_manager = form.cleaned_data['file'] + print(f'{self.file_manager=}') # Setup FileManager for order upload setup_valid = self.file_manager.setup() if setup_valid: @@ -637,13 +763,51 @@ class PurchaseOrderUpload(MultiStepFormView): self.columns = self.file_manager.columns() self.rows = self.file_manager.rows() - return form.files + # Save FileManager + # self.storage.set_step_data('file', self.file_manager) - def post(self, request, *args, **kwargs): - """ Perform the various 'POST' requests required. - """ - print('Posting!') - return super().post(*args, **kwargs) + def handleFieldSelection(self, form_data): + """ Process field matching """ + + # Extract form data + self.getTableDataFromForm(form_data) + + valid = len(self.missing_columns) == 0 and not self.duplicates + + if not valid: + raise ValidationError('Invalid data') + + def handlePartSelection(self, form_data): + pass + # print(f'{form_data=}') + + # def process_step(self, form): + # print(f'{self.steps.current=} | {form.data}') + # return self.get_form_step_data(form) + + def get_form_step_data(self, form): + print(f'{self.steps.current=}\n{form.data=}') + print(f'{self.file_manager=}') + # Process steps + if self.steps.current == 'upload': + self.handleFileUpload(form) + if self.steps.current == 'fields': + self.handleFieldSelection(form.data) + elif self.steps.current == 'parts': + self.handlePartSelection(form.data) + + return form.data + + # def get_all_cleaned_data(self): + # cleaned_data = super().get_all_cleaned_data() + # print(f'{self.steps.current=} | {cleaned_data}') + # return cleaned_data + + # def post(self, request, *args, **kwargs): + # """ Perform the various 'POST' requests required. + # """ + # print('Posting!') + # return super().post(*args, **kwargs) def done(self, form_list, **kwargs): return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) From 251603b69b81306a1a68083019492ec900457b19 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 May 2021 23:47:21 +0200 Subject: [PATCH 070/300] removing temp fix for invoke error --- tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks.py b/tasks.py index 6eed4c488e..3065d97243 100644 --- a/tasks.py +++ b/tasks.py @@ -65,7 +65,7 @@ def manage(c, cmd, pty=False): cmd - django command to run """ - c.run('cd "{path}" && python3 manage.py {cmd}'.format( + c.run('cd {path} && python3 manage.py {cmd}'.format( path=managePyDir(), cmd=cmd ), pty=pty) From 7a19145be15651be65af030480372c1feb5be878 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 5 May 2021 17:34:35 +1000 Subject: [PATCH 071/300] Disable wrapping for translation files This ensures that the updates pushed back from crowding don't have unnecessary file deltas Ref: https://docs.djangoproject.com/en/3.2/ref/django-admin/#django-admin-makemessages --- InvenTree/locale/de/LC_MESSAGES/django.mo | Bin 119528 -> 125311 bytes InvenTree/locale/de/LC_MESSAGES/django.po | 568 ++-- InvenTree/locale/en/LC_MESSAGES/django.po | 3236 +++++++++++---------- InvenTree/locale/es/LC_MESSAGES/django.mo | Bin 380 -> 327 bytes InvenTree/locale/es/LC_MESSAGES/django.po | 523 ++-- InvenTree/locale/fr/LC_MESSAGES/django.mo | Bin 379 -> 325 bytes InvenTree/locale/fr/LC_MESSAGES/django.po | 524 ++-- InvenTree/locale/it/LC_MESSAGES/django.mo | Bin 380 -> 327 bytes InvenTree/locale/it/LC_MESSAGES/django.po | 524 ++-- InvenTree/locale/ja/LC_MESSAGES/django.mo | Bin 373 -> 321 bytes InvenTree/locale/ja/LC_MESSAGES/django.po | 523 ++-- InvenTree/locale/pl/LC_MESSAGES/django.mo | Bin 526 -> 472 bytes InvenTree/locale/pl/LC_MESSAGES/django.po | 523 ++-- InvenTree/locale/ru/LC_MESSAGES/django.mo | Bin 518 -> 492 bytes InvenTree/locale/ru/LC_MESSAGES/django.po | 523 ++-- InvenTree/locale/tr/LC_MESSAGES/django.po | 640 ++-- InvenTree/locale/zh/LC_MESSAGES/django.mo | Bin 337 -> 331 bytes InvenTree/locale/zh/LC_MESSAGES/django.po | 524 ++-- tasks.py | 2 +- 19 files changed, 4358 insertions(+), 3752 deletions(-) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.mo b/InvenTree/locale/de/LC_MESSAGES/django.mo index 0dd13dedf0651b756b6cefbf5f93f05f1616d5e0..e90eab101b28a03f6724b788ea17be06861a736b 100644 GIT binary patch delta 41270 zcmbuo2Y8i5*S5Vky>|$mO|J=r-b?7cBOOArQy?TEg|3@krK1r9q*pWZkLL_xK!lpVLHDEZ*1DC<9a2I5V<8zo6p0T`W<=0^*825`^<1SO2MK~4zz$;Nq6W2Lv7n* z+cPa!TOP3e7hp;BZ(DiBnGQ!`+Qp&f34k6=(1uDQ*c)nvOQ1q^!16q-MEef(g+8;) z7Bz*^>j)J&H!KQ=L4UXa)`6#BIhb~~iDYG1i*~! zrZ1wlr55NdBuL-Nq^8>|b< z&M^*#zGguXJ12Q{S}x4{$iPGz8U8Ob0IGUwKa91>~w}@VPB|mQ=k_3A3UMCGqR>UV0@Omu;%EeHT zUI7)kE#5Z!e~gMk`jzE%tMCBI&>NT=W?x_&Dh+iXG=aHbe;5Gcp^|DB^nuS{KA2^p z$%Qgdb~-_AO&H9}{Em1k@@yv59xk#98?1a6l%da{LjOI~v3d&gz=|IlHiL4g4^(o+ zKpn@0miwS0bPdYhYv@tveHNKx))ZE!Jr2sl-B1zu3@SpGpjLJZDul0~Kg_n+TwnpP zJneB%Teu18?oWi;+P#*?pmO8PV)nlZl@|zQ@10A4VE~B9w8E-k;axqjS)2l7O1U0?V+LpSD{vP3u?vBp+cT&nQfNh2sJ($>e#+*IT6a<49f*jk@2ju3ZFo&C=trQaj2DjZRIzi zCVB$>V4CGduNo{%I{>Ob!g36h!}Fn5x)>_tA48pjLq_g#T(p8aP#(R4O0qO7jACJ^ zEUyaXU~9`>Q2K+QA`uU@;+at6--nuL6I95LLg`(Ha_9vtMgBR`t~4(jKj@-k0F=Ub z+nx*cI^G7gMOUBw`EEnouFxDTOj&MmME^E(bx(SQe* zsa6|9g`g&=2@ApQuq7M{i^GFfehVsDQ>-y>zg$p}XbCl8N2t(;LM>pl-&H)Qh7Um{(^cDk0yR;ljYi)EwbEM97q)?E z;YgSPj)RKa45)FQkEm!bwm}U%3NyotmbYO#+D~o!m2GF(Wb|`F87c*p{k5UCq$^Ah zW1$>)8>WI2EvG>i=yA-VqR_2{^6&uEfD=%Tor786P22tjDq<-U#yA~`( zyOnJZf#qqBv)lxg)K_3`o&Q%<(jdsO*(66ks1W(VtgsHIgOq6ykUP0(K*Fb-yiW1(_m9+ci@C__h} zPR(Vg34VieIKx&O87TeoQ2q5`cGwwe9yj!4qcXyFOoKA82xRF2ZCJ)eBmkE@jH|}>vl7+7?h!^ zmTh2T+QCrCxfaT?El?rf59P?$R{j{~qWu!ePPQFhMBWEDo+_G~E6mq9s{2=l|^FekhT^TB6O6J*7b-WR zpd9}Ide8sIRJ5YqFg5%d%8@Hjj@^X?;d7{~HP?QlUm5Bx*B0tVi-0xYOxykpDrxUp z{tTPZegUh)1_y}0LN}C(wqQ2Y%2z>oz7Hw_XJ8R{#mfJHI&PUiH9s`+K{?t8O0NSf z1f!vHVv`lw&)fB5~UC9@Io>4jG3_ zKz$k2fP-N#sO&!h%flP6B+Pu+M6k+XkMXb_g3@$^LY>=Luom13Tfm1Hgo;3lqeia)R4$Z;lGpT5QRq8D84Q6s|8X!CoMbuOayHb2 z?^!N`I&K@G_IeLg1P?=P-8rak5-NUv+p^wggG!?CI3RIFUhsyrl zQ0MtH)SlghCE!!25avB$-Ua2LAMNf?5u6N5!|kvf{1z65X-}GDEd@)`ZURd%zhfX3 zO*9KCWUF8kxCd(Q-at8&_msI}%R@z=4NMO^K{?hNN^dMI3+F@S#sSMyQ2Li_`zG}M z{qHdqIq(MRxa2-P;;nI_O={o<-?)I&460r3MdB-Lq+r(sN?z=%5J7F%qc1X z)o$?x@mHlk0u3Av724@g=XxFcl1kT2UmF_VF5Z$LPg{bl;;nj9C`}1;un@FzA_g{ zCMbupK}D__%mF(?ITQl3!&s;YPJ}vDA9>0C@1ml;JO?%K9+aV1PK+~h_&r8Q2L9Z7P0~AVml72!TV6-T;G@l)q~lX-w{AXo^^%_*p&b7lYTR{L2tJ33Sng{^uMBk2 zt`D`qevo-Rj#w(nfdx=Wu^MVcyI?-}1yt7l2z}v0sQV%Rbuu2hpjO=9as;eMdoI+9 z55vOng_Zk!Z!Ws#Fa`5FCQ(t6Ood9GxwgFmrltKc)P&oij^`ez964s&=WP31sJ*@m zwV)SJ3rKy#EUXBWeSfIa5CAhWzoR1+8SWzi41+Qh2Nj74mJ6T^Z-Ua>3l*{BmY1P! z%m=pr2`oVSPpAmxziAd!1y-V62YL!piJ(#pPKDkTLruILYEMtt_6?{=JcBau3TkV7 ze=zqzWmt-KT_{I`pjH}f`#rWj6)HDA_<{Iqr5g~4d!Y=Rf{Mr!C_}HIR-ECMVIHWJ z7lU%3DpdB@f{H+dWh_+4M?#IC4mD2#)P=R?7V*~vI}nJ6p>DJ@P##`}a^#`ye-0JO zRJVii#p zio`XjT=@l-gjw#I<5d;<(H;mDxdl*;t$?!o1*`+Vg+*ZAd*-XSCM>1%A4H`D9n+u` zK7sQ13{;YR4^zYJ_f5YKltVS3CTIn<@*YqQj)IEN2bPIeegW1%{uIjL@(+|d?0-)x z=@9gTT5%ZE7L4~Q@Fy9VmiAJpq+1I$@gC?s9Z=(LK;_0Om=WfFXttmz)RxqNT1ZQn z3ATsc^WU3F8U$fbE0416F;EjshPuf^*>p3UC*rR?KaD^ueF(kB>#_OyT?p#Dz6GLy)PlCz5m>{ zZ$s(7gqdK5pUs3mP!3jrl2`kg{a3aJAW&%g!b)%=EDd+U3h)}#gc*M^4*0>!w3|a6 zvyrd{oDb#5X;>59gVkZNCuU1}Kt(jrGRi|GJA$`iLpTd6d(T2e<}sAVS)ZB}<%J4e zY1^&~HNG{>0sFvgFdC+ZW1$?H4wVyYVI{a3de8q2Dw?3kuO=jApggPwwSvab1xG_o zwAk_!D7{0r{|wZg|7`inGTm<`H*!Hmst8o*YeDRJ9L=Z{N6;P0)6r0;VFAnvmqJav z8J2;EVNUn}YU|#>T(H11lVp{k7StMQqAt)Ia_C1p3RZ?oU_PDybKVLDVR<@IKR1T` zp(bhzl}v$9D~yH;@n|SVXFxeRALfB8ZF?`2Bd4tVYbZw_Sh?c`KVX>OkzN&;8ETKR zLwTML>R6S6n%E!uz33r%AN2nH&!39! z=+;mXm<&_FZBPStK}~!NmV@6xMIhZDCIb1OBIL5|iZCDT>QJHY02QIWQ1&9B93Axs z@t0r@0;a2%`xmq0mo z{w49ROXYh6x*`j`GNEb=<>5#u#o15>mO!n159|j|!J4rAYvV{T%u9PXtPkfvMdB=! zgZH75{Wa8ri+cVvd*llXAqcST{!pQghk83Mg_`IXl-{3ED=YZMI8*`3!Fo^;>;Zk@ zAgJ*RpjLhWYHOcBIpldxMWM>zaC(!iDAWooKxKD5s0cKH+T%{P9SAj1l;v2cB%252 z$VsRh^$ygEGdswu?%9UrZFie@kI93cw zUI|LS9+YF9tUMTMK|^eN98^SR!TdV^+o{w?a0cr5Wl8Dup4&XIBJCnjD{l{V9Q#^^ zLq#SIYTP)eJ41gs1S*MEK!tK2R0uD@ zs_>O<`=@q#leR0A1EZj}U_8`>d!Ul|IP`_o zCO~~+t%Gvx6jVrWL1p)EP#+dq(>lFbof|4*MWH6F1Qn^8Q1di{nx}JGr^mauK?sx- z1ED6E47K8=P$4`DwP#nM9CM^I6Xt<3ToB4|IVgu~K;=S9=-o0XJK<1SKL%<6^U`^Y zV5L<^gxbR|p&Ymg^TRah&B}^Gt;`q7U|r~436vv2P&efeD7~qcA3!;{25RE%wtdV) zMH8HdGVlm00xw|&m@9+H_C`<>^@kNs6$csSjeI2OK_p$O=SdI29C`XRLrtlS1vIS%|p?}b z8B`<#p+X)7b$^V8%7yVzIWp5r&fiih+N-TlH`XDj5Z;9@m?oQN|yDZBGLvb z*#_A5FenFSK-paewdb3mB7DfozlNoB{(qpN2{U9j6O@78*C*88c7TdZG*l$sg);O$ z)Lp&~>SeMC%8@-#dwmABfOjk_=5TudgfkrK!{k%w(TYB&B3^(pcnfNxdzMe3R`A-k zv*a`r=7kDz2}^&darL1>-2y7qouM3bLpe4CDrctTp|A?=_h1cp0>(k759eRmJ=Di! z=?Abb?ekE3mo=}`F$ETeli?aT9#+ifbWDQV;22mtzme~SRcSXUV74$0YT}ttr{yrz zv3>!ykdmH)rqTuKc#MZy(HiK251~KIT*xG61L!@^P^V-(42Q>HSy-{Kxd(c{cW94> zTJcNh3#$|{_5xu5ZO=R^3i$=7b6Uh@_NE6MKzlY+D4#-|j(SB+I~Z!*CRheOhuT6{ zF>~BXLFIriOb=^9MKr*&BV=J7M}I2H+PSu44b)3xCrk+sz|!zARD|wBC1aN2hDD%m zzDiK1qBGQlAyCIN8p{48s8jVJR1)rh-hcmhno4;Dx1a`QD`7m(4_&lNLY?PkP%G>S zwFUj5E|#~URyM)P=RvJ}GnAuyp&U33<=_n{$9`2?=RZS9bG{2fU5&M%j!P$~bC_Zz;2|`p_eT{irA_!=P699+Zb4 zLY?m|P>vjcx?;~lMd|_6#q=B0xa_6PMdkx_Rab*0U>B%}jDVVN0+gdON^|}tn2SIm z{t#*G#Ksi&HPK0^y*vZ8!tbDx>Mqo{*H8;^lsCzo4{BUfC_Am7 z=II7`Lp%Dx0NS323T6*Kf%5zm)PSo{9{&h6@R4mlgNnc_D82N)CaZHp?Rgm}$C^Vq z)Z5DAp&~oqaw{ZvJdU$ew094Uz>&qz>HXzX4r=eaLKzxlIRWYzEw=rep^NrskPF4} zBdiJYRW#?k6V&){s2m$-+wVhPegA(#r92(qS%vhK%=s<^mEE@m(a&hp-<;;Zph3~ThbsNo)cwTExfo(^@qet?R|BinvqnWDCdXr|hn ze}$?z0wq-~sJ&?eB@eXnVNl0%8r0|a9H?YE1a&&Tff|1emV>`Q*(q4Z==(!$WgwJ8 z$+ zs1J_qP+M`+@*&hc@C*_Ok0VzDb5|FEQY>!i3thBpz!I=K%n09xI+jzRLb=LvGnC=I zP%o>?P%D36``cmm4d>rjq9fO6m&lz#dEUdPPuC`?6r*aUWgAy5vX3)PP@L6_}>6 zNvhgVD;@}S^-h7>qBXD*JPsSf7f^d&w~28e9O_t(h8}q|or=!?5~yT526g;yLPelJ zQ}ZX9Sg2F5+Hxb*mTiYx=>b>+o`khvie@H9>cTp-!=Ut6LM>=hGtR$4bp(NU8Oou@ zRxw3$b1!6qT1j`P9}bJ4Lj4s~XupRt`~d1E{S7JyGPN*~EDUA0HuQmQp|aoI!eg?3 zFakO74%BIw4;7+SPzJX{O>hdz^KYQC{63UJnOmC3HGvu*2<2D|)WmN?IW!w8Qp=%| zbCZXPLV6f#;0Y+hSD^OvHI$)(t;~u`LwQ~m%AvYe-VDlcXDEC9pk7WPP~Qy^P zUE6*KYMzx)za#d*#ybDksOZ=fYiB|q0L#&KLtVAAp(fm5+b5xm_HC#M)3i6^^F!rE zZCDw$hZ;8y>XE!FlNM0NV}RvIs1VMD&EeND02b_Q zLf;Q+Z-+vSdmC!P_n;hG4_$B%R0OU<<=XGCD9qG_^RGSh>tc>iQ>c{;fKnI*HDEE+ z-ff1upgyzmAD||B2EAL+)tsXIPl@u zHQ^ShiB8)7yHG3n6Y9gGW_PpKji9!$9aJR3EJs6)pAD50o1j*{7izrcODYP6ao^72pvYC+wMt)U_n2`j=0P+7el>K?cW6}fc1%!Eau?3RPdl>n$? z*$H~z|3j!K2PQ&Iun;OD`=LBP4duXhP=+2ug*a_*(=GtDr&XXr-3n@a7?h*KpdvT} z%HBFCJ9}VZo&WPxt@YGpfY`xunNSD^GC z+V&f$iL>`L^Oc3(_kRGD%ye{xQV4=t!6@jR2r9%&p$mQqwW7yR`WgEfM~g!(q#o3` zZm=edu>Gr`7V;^SV`uwu{PG zr=a&ZL*>FFD7!fW&6fE?MW!j#+w-kJkGWC<5!65s4&~u8s0eJeJOq^+XQ8gnr%;A{ z2ACwQ2HVhf!l%ubp-l|!HOhjrxo%^;>3kvg4sY+!G)WkcWlIt_56$I@G}}}uW#G_l;OsqLQsZk!s@UC)Tx*ZwbB((j_iiI881L3>9Db^%xo_JrDk*-(+&43)H}pd$7d zD!J1{aQ;hC$xTHosSCBoU0`MCh6?EiP!U)U<-q4q`uAZ4m}0PTup*SbFsLu6Sy0Kn z2Pz_up-xfiNHb5FNY1}jS_^?f)g7uG50!NDp;odRy5MCP4gY}3{y|aZ%Vq-9M2DaY zK7$(P6K!&+2GqoXuo9dA6_Fj$oPT+I8G(+8V~E+Cj8Jbk7wiNpK!w(053x9lQNd-+ThA8k8fQpl-lu zs0d7h-v9mo3MzVyegeHoW_b=ONp3@39O*}!9C1MztY+C6>K+&ZwN*=?R=Cr)Pea`! zx1bjK4C;F#&)fF>-{fuMaSy1K4TMeM2&mA03N_(9sBBLAj&Z0qRPJgdOtxI{1a+?kqP?3;{28KR(O9yW${obk5@oVybo%E zE6@dhfl9U<6U|StB2W|dfI5cpP^VxlECUxnZN*`z<9Go||0!&)^PhE+Nusx)LOIql z0V?@6Lfr$mp&v{&+3aN%s8H9m?PgG0*&1pqLZGsL7}Sa54C{yP!V$5b_|sM6j&0z4|QtxP2v12EAJps zNFG3iEbUbD{;vdOuq#wZ2SFJc4>iFYsI6K8wem!$tvU~N)7^ubFy%Dkcv)DEb}i_F z!P7XmO1_B*i_A96xwA{Of z?Vyfb4AckC0uL2=dH^bvm!Jkdf<Zs1PrPUEm>@0_K@#E~tD^TUN}rYgq=s3_AaxDsLv77csPQMDCca?#3-rkIOz)dem4KCL`$8G) z4>d3XR)r&=?(j`e$+`>5@h_nE`YO}{9$PvSOayYmO2~^rjqePl*C&DVuMkBc&_wS* zCEs+Ydtn)D3|B+F?e1It0@Klc0Toi`2PWh>pzIZca?BrUAq}7+*BWX|yFrZ$`GE5; z#bF3E@kFThhfs#rK{>VyYAcRG8N39w1-GCKzqbA97MKYNK#ebNSsNsz4 z4;5wa5vZj45mtj)7McsG39LXn63X)rp)Q;aP&slE>U7+In&3~^1m^kBIM549J`if} z$JzE`s4evDprUho5-M44K^e%r$h_S;L9OInD9=BHio_|XV|xwCp%ROY!;PU9G#EC3 zbD%D)b5IjLh03vXOYHftLq!)$Bd8SyTgE{dngA7opGoE)cE$6fiQq}EG!2-JE%Jn?P#bKd!R3z1vSxrsK}jxMc`eidnMflvt|C!d&(g8 zJdO@jq!0u(@w-sTvluEV_dsRwS*VrXg>vW#l)m$0^W~GnvL)2990TRZBB;II0Tr=F zP+O2=qmq*ISBZ*3-_)`nRES4Ft!NySq4`jbY=m;)7*s^QhSK{HYTWNoNu6SoiEKKk zY%dNK;Yv_?O<-D`|F%?Qpes~JL!lIhSx$#q=|@nGZiWisNvL}-ZwzzL{{zO(H|(7R<@%=jEzIR6T183fw%hEU1a2g>kps1VPv@}*FEd!Zb-1eIhz z!3HqPRx@Ec*o1aps4QOrbyI!`b3VZ`yu*weOSQjYy0uL2={smNMGw(DLR<~>e zwZZ{VFQsv?EL;tB?9RgG@K30{ZI);p>j33I6x7{62`ZxVp^|Z(rDvzD9I-qLy?bW) z2)1OvYp7$>e3yAixh*F{O|TBSU?TK~mta+xVYgXO1E{U-3guWd-@LcYeLr> zDnubr4vez$DNtEE7j}Rvpd#_BmFL)J94`))D*;eR*BvUi#zQ6FYA6R!LoM_!EYAFn zwELZohOj);`#%EerkV+Lk!*w2;BKhb@MEZ?dkK{jIS-htwFcAz8o=tX3)Dq39qJg* zhl<<^D7_ufBTr6J(cavHQcU%!aU>^HB&tD$H~`8(Z>ZOABvfdJT26q{n+x?i{us)^ zZBWU55$cpU4w?v-Imr2!pcw+4>qw{xr$agN0aP-sf$}&JdP8XY??Q$AIaE?*K4e(J zvJRAfCn(1vp^|e7biqA`JZ6Hc2(-r!pd5JxwbFctjU(lu_PjRK%DY2N*x&XKgVLX5 z+aEx!c#V~xg|d4SYHQxu{_371#irEWLIsZ+y(UoSzprgifpTm) zRFWNpx`OXOZS5PVTq%6aY(;gb-0BIHYaS03g=m>o*bm#&z5xTE|7T9`e~v2-Ds-oy zvimhuf0^UvA{qo0;ssD!w+%LfhhZ_8{&Qou0<24WG$c7a{Aaez3J*iA_&${9*-w}~ zuLR|BQ>ZN(2$d6~pk7MTp|;|Es2te{_3}9krGEj+?vGG*vz#;^HonmN`@bg@DY~Hy z4}~%~2`Y4pp-#sRsF%@MDE%Lx_WW0<3DcZ1{rRCUZC|Kyy`a}FbkUv!wWVudIi3GA zRJ4*mpbVuxZ7!sImc^ka@`YMK1L(~GC__`ALcAF&IlqEBmRF%p(><69K7)EkytGXH z1?OLevr_5fmAY_F-a8x%hOJP!SD#|2g{r_**yieqrC~%fUjXiSnZq%tsAbOJqhYw zD0kleZ3(uJ97=u$z6)=k=lp+2CFUz9|I1a9<7=m54qOhUQ1u(9V<|iY+rt4D%(>nQ z>(IUmbv653G@n>)q1x|2Ik+84?;&gg%Um+aJQ!A?J=a4;7sY2#=kYPr3bS8!IwrvW zQ2n=|j$M{3PRB}E3pR(>pt8HvRr9)S3)|8j2V23jP!1IM*4TXu4x_yqc88wA-x9#;kcna#ixMk%pp(2v|ra6}7 zq1x@B>;*&JBST>>o&Tv+1%8?mXVF64;ZPUdh})ch4VZyo2Ye5z-TIE1ptGe1%CQYF1x&Qu z1C_M~Z{KzmZwcGR_O1eLYTppvfx zl;{0yI~MAO8wVAkDNy<=EH^@Bdm>B&_d?yQhi&_;hl*Y%7oj}63k$$sp$2BVXZAW5 ztV+8)R0R4%849u-0-dz$F(?}|?bTq)9`;X>sEC(tD|-mzQ9gko&ps5E@Vt%ilq^#+ z(N4jD-+4;#yg}X#qg|2bV&JE=H>2-E`wsQN^kqOE2KhR7?8e4$NG~8eviBGBXXUii7&!YYbPcDpIgxeUf5>A2d!>Z_vqAxwXLtAAQ?FaB} zCgGR3<2Y?6&Lx!=w4Whg&7^l3x0sGe$O=&3;-Rt)!EvkIP6p^$MLR$BqC5v_=jBN% z*KK7iTuFZ@e8Cf7C(Xe`Rct*i^6uz-%sl0&zs*8Y(=G^=Z=P@INU-6c?cf{aud?6D zXP`4NnFCUI!o!bR$JZFj3Ex9^1@-K9j4$;GjLDYFc9P+nRNkk*UK;lQFiK%oDK8UM z=BY_%xnzzMN2e9C(F`oX%Fe-e=>G)WA&gB)zsfb91?Z{FMy?Z5kG4KI6=@f;7{=w{ z38S4UY5$L5U_MGgJkRJ*`Oq58O*=OORYt?+@CHUlVq`Kp%c$$RR@umt4Y^9Fb!0a> z+`!&a%kqVtgZ1-@rE$>oJK8cRja52;Y$}7-A$w(wJ-2!f7~>)mCDHvE+1EHWg{Qt9 zE45##H)H$)D{Bk)VmC2CPN-d)vN-;!ps}aJp+?%fQj_CM0SPx zTAmGzX+YlrWGc^*U-&bo986$Kc%dKJPun~nD`f-LOd;a7V#WL{*vbx zbaHqYlpdpJU_ZvWnD7`+4HQe;$%mpmgZ|p+C6z%89>(KO-+So3O6q{0q1%_fCeWAX zSL$wb-ljf?gu0KPvQJy2-Ea{|F)I#nuBzfS$MX*!~) z*Q5Rjd0C8Ir9KY_lFC<%uS4Gv^jru-t(~O)N%W0Ge-~p_w(#^u_ObR~C710;hoOGB zpAQ2~QJ4n@()T5NOuIe|=1I+S1YN$&9Am5_@58&;T8d1CZw+tRh29Zc|AlcXIcVQQ zUd&@BUPnXU>E(G+U}!n~45h3%vl^X`=zq%KBGeBfk3gp-I=gAF;>m<;CH?R5=u>Vj z{lCI&v)2qMStJkuF-1-8Y| z+GOKHsqaR28}bm8zu~z}yEgLAc^Y6VBdpKZL-aXQv;ScTzd<+=mSSLSI(E|zhQm)#ulf44R*$*VE=!ob0D2< zSz!%0gU$##la~Pu^ym4W!G+Opfo^wn>QKMS^C5lF49H4<8^)__(L_9FcvNQaM4{J| zc0uZ$uyI29*ABr%o|<%iN_zzcI?^6u4Iy&Ww)LIxH4~}?VL;_6<5arCay*aeUvC$n z@BFFQN-D*yZc^Km0zqaJ^!cokkHLejQUvl~+MALYIE+qn+g~1Ms?y&c*;_bsh_D0$?x&pM?R1-RhaCuo#QC-Q^+!7V=Vn4+JBXIt-@j0m-Zf5%}$gPPO$yb z{Q!f5Rk5X&vgBnLWBSwA7v|(Ci2g$Cs{CweTKtO+^xC7d8u=pTcYI4jOxAImW7P%ZlM@TeqO zs$Rp6y^rByv^~F3*@|!?jh75QOZ^>YaGT(^eT~XiwU*+@j-M1nE$^fFYGz)RUJJcJLF7rXy-er7?Qt zZC{AxMK~FS{Pc~*UMikR$a?VRn%zv8B&Ik_jBo+O6MdhppG08FNC0Shx>Doz) zQt!gE7DM{m!52_vA!Ev*tCE>|3-~>HD&JZ*fZmQ;`xyN3bb3Jqw)mf%Xp5`cbR7kHdGRs`~daY^hNTd zrEa?%iHyIQiuKo^G9GDr8HUv{dIjaAa+}IK$Uo&7%kvY@Eewz5nZQif zB`vZWR#pm~YuH_keobT*=`RPH+y37yJ%3Ocih&U8L_7mjremx&ef6yI04vx3=jm!z z_d{gecxss;j@;;eZVi{F9)t}Qnb^la&ho6Xvd`fq{TJPj(D~X5zs1;el-|Nf8z!1T zyF1S&CR~KhbC{ZEAbl#8Wtno?jz7jYkFD$PbSjh3abe?8pWWL+VrE zDD*c_@4@4#i}EWJ&eK@IptC6Svy;t3rZUU6+t9z2ewBCFF%*ZglzAGmfR`cGrzE-wvS9Tk_Je1%>%M9eGrGTAeoZseEMR;nX{OCFUP_ z*n&3b-bSxFI(K-oQ$K^u2j_3Xg;1qG&yTuMl1dfZ@f!pD?OwiXCmM%RZe(3Bpz?;t zAN}4u=UAc2G0St-&V6L<8S}lhv6cSxjK75a{?^WLy-_C8@ImP_Is$1ogy-#`B^U|A z;3OD_>^+_|=v3s{K|P$l0gSI>9Y)R3gz-tGxs|_bC%nwKq*4_<&&L?}1w%z?d}cd4 z!cUN0wCy>T-7(@uzY!KHQqRwrEa=UJ7hzoG$1a5>Kh=zNRLL7pzOb6}$) z{e6?!c+b31QNTb2I#x5N2#=e3l=bvaScLXujJ(ExN^@&uH0^2h?}s~hBG73LcOk0= z1DSLZk4jJaR0=S*ksa@owEp1;n&L!B6#hW55A~!{7GrZU)|KZMgavq}CUwFe&|l9a zgLr=AnZvUR*?nvlW6S_-J%huL*Q6ecyel>vFxJzB#ycoyq9YGXDkD%Xh|*RDCYAi? zbfWQ|)$3>JgSOR$v|n~SIy z&|j1uSfd(K*w)+8d60pXdFn8*KD>?WIfFY4YFTpXGJH6b>7GJRX|szB>lOt-L+;$GcFZvl^EUsbr5c}UOFw+ z`7?cQP~60T$>>B<{|0$(>Yb4#l{B{Qhr9_ot$9k~*isaVQ&$-dukx(mc{kZuPf7-j zVWOn+9qoNQDo*4T;1cUphhzg?^i883hwfW&4|?Tb874kMeIbv^3uK@3>}29Vp5FB5 zHeLFs$MF;YY>Khxc9N_zMm-eeq_USuW+K~$>^J&Vey81waX(pSjg%aqe z7w{`49Se8a$)m8VlAq@{TUR@q{-W>zV?}vXzQ$lGWOc3KuaNzOk!s#v{+xkc5bgD} zXTt0lD~xUtocE(IFYWJS2QEe4(K=9x{_Mzm!l(4j;(1Lw>HXsfrco8)#~7)IQauLy zfCw(drED#mBhzkqrk>iOY$*dCp` z)FaS8PkoEN|G%K)5khT6f7pYL&D576Pb#%&KSX{EPD5uh2J~a_*JL_jv^ykgmq90~ z9ATWwE}pK)>m~Ii#lIke0?7ssWU~2okOq#Tzbv6lDqZP2jeY`p4Uw0?sV6)alG#Yo zji6uiR6w^jk4h!D6B`~kjUH6y@w{(4SHZqKQ!uy&`BrptU}PqBm1fkN(Wf#H$4*h- zZ<^kJer5I4m``74bWY;f4|16Lc=`_@pOEwyr4n=uW5Rq0{TZ~6cKKvR#xW>0?GCUR zk4h1iNC~vF)hlH|!aO1> zKE`f$U~n)F#IiLJQN#SUjoMoyRqoKJxHxyD(Ms~W!MshMj@efG;Ay8PL_MzHsL0an zvOCBfKGf|BwCPj9#qI{ix(VhWatNQKTpA71i3JC{;=<6jlgdtvJ2X7jbSc{^U@F)Z z6y_#EUN>W-0|&c8q9RBSKS#@m2=})1hXbAIBBFu*!z=(LIc!WEMRNPkac)h~;|C!}U+w15M7`H9_cKVF-8vpE* zVuX8M_n+IOwbl}f^GskV*$txhV$-XpYa%kQt#=S?zz?=dWz+%%b+upp%~ zB*B%_S#aLqi|I2a%l^a{DV-HFd6FV-62lb{9y!Q0jI<1o#Ov^2A{-SP8$KXn1bY?~ z7*DLj<6L1V1V)%t9^hv4kO%v@I+)FfaSw@i$Hut=U6Jl#|2ofpjxOwo)nI=T{IfY{ zd;U&0dfCK4o|0vPIOK6jP$IJP$?))njy36EstUki=qit%%`w0T01<4ANx zKphpl8Nh~;Z#vJ(ZFv=9xph3;L4gsmQMxgLy#|77%g_JtL>6ORvE*}*Jcx-JY-UpQ z10zTH)g2I1KLeh4r;m+~j*bW?|8d1y^?E}H|LT%Km)jE=7ZdK5C;#b)H(>wah&k~j zxp&@q(8(Z4X)kNu~MEom5+4V}SG};|Q z(AWe{8ZVnD?l7;4*O~@|N0RY_y|<8G;@ND@E-5N=SalrTgGrsR@SrfxCBw|Ck3*?9 z41RD{?Y$Z7myj!`bALx~){&Juwb*q9v~L^hJx_n1xhO8q7_*>%Z{1&>o3o|C^NPO8 zo6V#zM<_lzIFNfT@l;OdyfoFAKyT9^93u#huB1P<|0$Id62^tcMYw$j1jZ!x%&ShDF6k=(EGTW6;bnSi%^##4m9~LFc9v+04$GYe2zHSe)INKcQq1XWxLTzLou5 z{*`K1s+^%sU~HUkmzcoF*oeTmsF>O=B$1)a>iKg#>4DXU>Gh6`cXjZi(MlbnbJyT7>J38_IWBuy2Q$sF8Zh zM;uv+udYZ^GcJ+;5dO>*S*-K1zU`vo!bc`lsp?$jaSh^o&1ks-2QXz&SOhN}JR0Wa zJ1w$;D>%@FZ;?@?czongF7w#9BP;np3uSeY!O<~M!SRE*^+Ur4#5w+s(Ep}gk1@=< zjSqt`E%$$Elw5KpcOm(N>iegI|Lz^YONEU{zRdL63-3}Bj#qVdO_vm+go4$a(JlYS z*bo@4`+tm1!kB8#M@0fm9>w~0_I@q0=P}7wn-Edmx!OO;1FNJp*lJKzu-oyEgd7kU z?~Y8YR>S!`WkTvY&g_X5>NvYQ3%1aUZ%_nZp8uI@iDT zFWF8emap%el|FS$SYX6}gbuBoK8fEncmC;2{Jo{qFMS$cuLFstJ3E`D&ieOwb7U&4 zcjisxzk_=)WgV0Fz8nJY6yCIVSYbfY2d#3`HOPL_;&hx>Bf;6t>60nBII(?i=Yf>P zn!5+Epw8iLSIaQo%GO#V?^i81OL(MTVy6Dit*LS*9VFLKP6da-9oZmZf3Wl2#9nS^ z&J?BJa+C5hGl(%sc3f_)n2+HKd_NKtcVxnla?X67q$8YcnoxJB*ORb7{HfqQ+}cW6 zjMbaKeCP6Y!1smK(J!VW`$)iO4t+?nRp1C;y}tY=iquzc*T~Q#`y$vHGOMQ>V+o#6 z=VfPbLeDVg@`M`$op}>pg*hu_Q@nj!@JZ%%H6}QL|MaDA;=pj{S*L&3$Pn-D{$p3M zoc!SYqc5@6AZN)G75<((#+5wH{>oQQX{dYHk(FT)afy8fJMX8-&6OG+;rQE+IJuS3 zE6(ZL)mPb09L>)EOU0gqe~olIWRBZ5i0us@z)0`4`1jb@#Bbu9OVgwe_H(rMZe7CI z?ao{Yb4EEYIpY!sjdrfiL=Z^(IF%-IC1T4 z=b}_OlP{RNE1o?{?DC#-OxlFSi<}WP0^E^DcCsy8vo7nrYgjxNq`f+m$CgWuakp}RiuQM#l3y zJW??TIkGRt6)bzP$<8TXw*R~f6a0JdUTC$=8By&Yi!p8{yP3ULx%a*BkGnMC+%{*? z#8caxqceM&u*^34HS*tIRINEc{QlRADlmpi*XAro;mFQV?wv4qjNVl43f!!`{V-;( z-dG*TVY=n{dxN6q=L!ht2dF+LI6>x6vauxytDA4Sq&*~)+TlzgWC3 zcy$$WH%B*+zsCGE5noO*{17xFYI|KVmid0*2M+4)81E_M4V>hhpPc(wKoU9(bmnf9 ze3}1uVYq&T|Br5LQC!TCm3#sGHD_%{vt()dcldQ9{M(nmmPsi7n-}Eyf9!#xs&lO5 z@kIU|DSbr}c9$;XkU&08lDqVuVfZ^}{||ZLNuC(q{Z8^MGTE*ezmf&$KQo3njtmdw zXQ)1=lBJLL#Q*E(i;j+_;pFu3ewp!mhF=$LY_gi9i1k|0=QiJu-pzLLDI7G2-!Q%{ z|Naf5xbx}23y&{EB1jhT>&MU0L@ArFtUmAj5{I466wZi*(np>B5+)yY)@bRy_soT^ zF=0nmM#Q-~M8$^dZ!p6KjS=4U|9!Cd_ST;RyaD?A2Ko2tHEaLxne(64|Fvz#cHp46c>eGbD{m9$ z9COB{%Gq?d_xQTHc4}iYCNMGMNoTW^t=jR6%KHh|()$~0Xyo%kE44!s+kW9(p28CzW4;#nx*?wWQTo@n$G?6$bT+>k^c9r+SA*U=++2M3 z@dMu+1~SamIx13s^5n}`)9Y$76VPYBWSFg~Z#C~P74Ppgb2)myXZYUNj+k7MF;4kN wj+^~h@=JVlhHnlM<-j@Tl++RWxs=fCymNfjq;yT%H?#Tw!|U?%^G?_Q2TfN?TmS$7 delta 36008 zcmZ|X1$0%{qW1m069@!%hip8ABtX#M?#0~$36K&3B*CE@E$-0Z#oa9wEmA02tWcn6 zOK~kuTfYCZ=ghsl-+13O#=5`hKG#lr?m3??Bzv$jnfqpjBy$`*wS63pT-Y$g;pmv$ z;TRUKREOimSchW)dFaMTKn z#iTeBQ{Y^zNB@rH1hh0yu?oIKUo0`v;V6U^Py^_SSuqARqlq>?&$`v7pTL6T|Au++ zKU90UCz*B%V>RMs(XE*bCZHvmXWfX!i66ose1$2|HQAI4M6FO&%!|#i1jb8!u@WFQGT)x$9Z&bF?`G{pB{COm=Kf}5y@ z-eM7S&M@_gqGnhb(_wuqjO{Tsjz-OV2I{u$aTCzqT*0(>2Q{*nsD?hGw#H|s8DI|7 zfJ&e`sEVnuDXLy4o8JR75Fdc)aRTZrEU@uCHts%6K&SLEY5;#@2K1g~I>>@bFKjJ~ z`H9y-&7>Cw;%wAeIAr|;HS?si%^3y>QGkA0S`U9;LQs zMeT83EQ$3|d;blpfo14}XHf(B)q2W5khH>%xPHokBH>+eUx z783H|In057qZ&xF&{W8cnn@wlOhZviT^lukW~he4ZM-*TBko2W&bg?1i&3|2y>+_^ zsG+^qD{F6KX&KHeL#|5U-CKSeUgRs@zD_%qO8{x&n0=H=x=-idx}oNIAFT z4FS(me{X*6a-$AgO?2TPRQ^00UxWHpJb~Jh7pR84mzb^0j+#&?s-s4z0Y#z)G72?; z`IuSve=7kUuH)#Bzo9BPml|`R8Y+o?*a&lDG}gn(s9SN_rhi18iEPWvk5m9^B|4)9 z+5rm; z|M#el16G(rSq0r1X)OX;f!3%2^u(MPhuY)msD_tdKHOpBS1=dx$EbFauQV%@168ja zYQ}Xj4|cNg;i!SnTFLrrM5{>99`8lX^dxHLe_}bzyvm&VMyQG%Py_0N+SAdf4i}(S zVm*2e8>+o)sPeCEe)83(Uf$KLzcNBekYCx1Fx1QjqZ!%-bfM0K#prf)?J z@WtR z8mNwe*cx>`$DsCp0;a`fs3qQpsd2CM1g0Q<1y%koy6_X~Oyt^W22cdGqV948G7xBt z8L=zsR1d&RI1AI^8k_%vji15Hq~Amh=rwAFNp_ib{7{FqB&z+dPy_9PYA@QPyB%%< zYG@{^p*5(H??x@vc~r&Qm<6AqW|%a=#M7b9LSa-#B~TsIM9sJ*s{O90_6MQLjmLDl z{|gA{aBM)Wz^|x^4^cCEi%Bv4ZZnXqsPuxU??qMAhpRJ|#gR7t1L|;IxBh{(i9g0N z81e%vr28L9KubLuHN&~65pG7!^f3D28JqqTb*&tG%s)4zLakIORJj_cZ+$n+h9gm* z-uYM=524CA_Oky9xCrR5RYf(_8`Z%u)PTmL&cyfDeW(tuq6Yd7^J9vA)Wu-TiVLwQ z?!bb08*`w~elxJV`&s|OB$OvX_p&R7;#jPU2T=_tKVX(J5Oo$xp$1qT8)732!3C(_ zjI*ej|B5R240R?x+VqqM&59Q|=r#?8lA!xt2X)=rT02?0p&IIGjYFN05vV<$f?Byb zs4ZK8TJp`Pb}yp__5gKQpQBd%gWF~l`q6X{gen+{*|93>@U=tF^+C-v8rAVq>sr(R zx1!F{epLPi^ulZCjWNJP=iN)5|P3T8F>0vW~f~bl`QKz>w>N-VP zhoJ^I8I$9D8((hYTTy3X4{Bl;khA4>JRzV%dRLO?V611sYTER4l|HWgc= z;{8!0UxXUiHq>c9k80<4^uY(H6?ty`fLamn6XsvXWyB=Jo1S3(HIr5(XeP0!LpKRa z;d<0aZ(~w?hPr02QRTc(nia{9$%$7&m8*@Kc|-J^1x!JF80r&04z-dCPO|208@m z;4Du%`+wbLys@S^XF4j3`6*Z*T^NmCI1ROQGf_*q5H;|nm=-tL_yJ5w{FIGfLDl=y z#-Cw2`geRHpuJCZ-W14(nt322Z{e&qj5;6jgpB>bC61 zym$jOk?Gzq5xFI8ki27qZ$lH4X7_>z`>}~KH0hiwe&ks?VLr`yN~+t z{EgbO>=#Y_G8ei3TH<;nsG;5%f+JBsGCOSgW6VJOGiqQNE}1it4>hyOs17^X^nu8a zi(?jM#C52S51>}yy3POh66>#}%=D|-BQZTrMNMc4YHN0)4(%@(gzifO^nviYYX0SLa?D1&t~Csc5g&r3 zaUE(UZrk+Fs4rcyYvxczqs~Y_)Y%zgU79!Wv?N~-Yhh(EkaQtB7M^Sry z4mG3Om>r*@W|r)_=^#653jjRe==uHskAP;L z;-(ouF4XDIi&}ve*7m49?TTt37S*8}^}(8k>R^#|9qNmhfEwT-)IcuT{989!e=X$` z64X%ATc&}`)_kaji=ir3LfwwKsFmo9I{ne8a-*!%Q3F|wTJrU%l{kVr^^Y(&X1nb+ zr@72+^S50~bdljkeJGZo8a|9VeCJRr@CenwC)D0%zhnNg2}TVp3N^5ys53JSbKrW^ zN*u#nc-2in_x3I7dgZ!n{>p8JTDp-~1Sg>y-ia0PDEgt}5A)Zr3pK+AsGsi`RDL{a zzzL``_A~1GeX#lN&jd6gzdua}A()qVHPi^ZVICY|{obY@z_O%Y$6(BO&zzm=sQX_B zHRC3zThI%2#$r(u8H;R<+cBGf3T{B1h2yBhbsM$hPf%On^OqTUCe+^MK$R7m0u0>VLNo|$7DDG?e#2Fd<&}MW2lk;it6w#CdYR+ z-SNnr?$oHIErL2^O|USI#6Vn&>hLmZ03R>}GdyPhwa2v{o5R!@HIR5LhdZzgKE-5M z;E7q%Kx=u_7SzS6*ba4A7ob*V4{E^IP!swCHIY{~p6n^>uLiO_HGAWa+M5dKiw#i& zYK0m=ENX^Bu@Y`Tb?^vN;oq1V9nZ`J(x8iI9aKL(twT`dCcABc`IwS~z1HK_iTvEteVE)Q31~_FLLIVCs2OE> zVLI|djWiI0u{>%Zk=D_uh8Ce3{sGhA8PtS+$8`7rHLwqu79B4=huQ5&M?eXMQ5}~x z8IG!`fwi{jQRq#)zjZKbONOIXWGrf>W}-S?gt`@LQ3E@K>G4C(P3 z9R{KfT{Tq0gHR2PMa_H>>JyxRMe%P;f_{IS@&!=kOJD%jL#;p@Y6ZrkR%o)~y8jCZ zsNrR(rQU~Hk&~zaTti*U`!@bBYKAFZn;B(6mGeiHD~XH|2ZmtkPi7`ntxZrX(gih; z{-`rC4E05vfEw5uo4yNG-hG6CM)sS{c!ZkKI~z~_k6DS#n1l54SQ%TQuHS6bwOxqC za3yNszoM?=pVsH70enQ&Oa8CtaB}|%)Fhz*YDpteBOhVoQ&0n3f%*~Ig}L!6mcVzI z4U7C|RYA=bO>8@={9*J=1T~O{UQV~?Q~AyoOzUkb znfpe1n>K`lP0O0aSW5)LwT)Ew$UG&%x5fw_+K*kF_w5kJEFu!cp~R zxe0_4*oj)g=cpNFOlDRf5H*ufRELpR4aZ_}JdXN9p&D*x?Sfj7Xw=yn zW8?EsXJ#|fuG?{hfcE$TYKi|a8IHH84wI%Z9R{L0sE@ivZBTm~gIbxHsFm1+YG*g< zlYI(x7|)>w@;hp)Ut(R||KuqZ;GSY_oR6B(9aM*ptnX0``lK=)rL<;7O~B8_i=#R$ zk6Pl|*5)?93u>jm#`L=X{RybTIMm2yp$^SD)E?hK-QNtU%|NqZ4dP*_pXZhM6<)<) zES$!irBkw>@2W@)Jv`)|e<5CrL2az#>fEr4`viKNvI`gM9hqD$|B<@BHWFP8G z97cU&&!e`)C%tLMg*yE$Fc2rA29{v`3w78tXW;&8grOPCVfqI3P5&OX_vcYxy7w4~ znKPPG?MB__wWtA~MolD1CR0BIs}m1LZS88*Eqj4l*?`PWM^_BX%>A!N;3x^|FijQ{ zFO90`Mt}SnHS?F~gYQs#_#f)f`DQgMlF^zEHIWjiL)Xow4?=z7$Dub)a}y{`U>0gg z_M#5cE$a)^Or6=xsV;!(uq^6&RYP^q8np#cs5A5}>I1e2i{egHy*sFZKSme2-xAP$ z%$nWIuqbNDOQ2@j2({NOZF)GWfsv?zPDTx25$f7)Lk;XF8^4aap3hJpwiG$cVb70z zXWWir1k_M9)U|7dTB7!->({VGiB@o&>ZsqfsNBg4*k~s4v}S)Ti|f7QiQ{6-b}UbeIb@(1JD|fLhU#sEO1; zb=(*=kPbFIM(X|#A)vh(~~9a+^~>4yzL1iCW^fsDY== zVaI%ox^Hlc3X^GN0M&Jg9+HLM>@Co8Akxv=gms zP-o^CYU}RWc#`~1&p(K`P;W`mtDs+JgVEE_xR- zd)5&3DQ%5fp&6(T&MH)c`%x=#(Wbw#>8T2vFKj;aBflPU2HcKF0;(8?lW?Lfkj3AO zybS8g)(q=l6zWsG1GUH3(I4-lzIf@1nBNG0tU$aOR>7&La%ZjYu#)b-E5MxQPN3ePZdDON06ZJRaW7Jv6SbNs5~Wa-a@l5c*+l)M4w6`m~Nl{joU*)!`OYyGKx4 zaL?waDZ%~MX)jX3jI=!l67PdLr3+EN4J%L$?L-aaXVd_0+WdE@fg}&HdyhKp&9DG| zgX(xW>euu%>ef6D;r?sMbC)z0M&0ics1<08`UJPL`JJpi(M5U;s)Jdm!?+vuJvfT0 zf7|*P)$Uu=3S}x~K2(L=1XQpLYKGOUEl_*c1J&SA)K@&&LUhN8B_-I;(o7>Vj&5vpJUmc-Mjv*9RXW>6gUYuE^jV{fd1i&0y5 z7d4@@WzDV1ff`^D)U_>xIx8KK+v9c&A)xE99YZi>Idh6DTWg`Vs3B@*t*|V1MP1kV zsJ*^~x?YY@Q@$cJa~nI>bpUn1N(L{dxvs7Tx~}1U&a1HR2AaQ`!$TklCmu zJB4cK0ct=WP#q?zXa@=qUzN~mFtXJ$^NL0Ct@(pK~3l=>hzzh%>CDCeno=z zG<_9wJ^WEi*vQ7aVm0F9ZTuvvqZgPTeX5$X6M*^6c#1^0o8878s_%Y zLT$NwI05bDSk#`(LM`QT)PVM(&cZp=fNo$#e1-ai7OQDipd)I}N20c5HtH5^vK~XN z;7zQ9u3DZy-Q13z1hn+)QD@*Vs^SS$hj&l|dy6jgsclxEFsj2^sJ(21YG(-Qw#-0H zWRuN5jw=5UwRQhsF5UkObxcMvR7cg(vlXao(;d~&K-6`dj{5K%N8Mv*T~j|DYQXtX z<;$T4)D-o7=!q^IWAj%^`ga^4pgp}}Gv1&orm1Hvh-$DRYGy4_Gl{YJV^N1|A!_9k zP~Z4pP&0jlYAjCJ??=^hUm>8qdw^>A6Kdq?o0ypu zLdDCVM%(~ZzN3xzMNME7s>As-ZakJRTHGx_fjJ?pU zit`Dm;7-(1A48?zvVOE?Zf*YIv^eT#wJU06dZSig6zb5}tdPSI4zT&{DQSHSjfR??<8rv;h5Z2daTfsF}V*HSF8gtc)KjKLl03F}g4kbqyz? zekC`eCU~VS_g{PeiUc*7w4E71ZgdeZg_>DQRKq<`107?Xi|S|ts{S$5fNr9`3$JZ{ zlJ+J)4=TS5YO5Q%38;auQ6n0IYUq0`g9)fx@eEZlMF%qw7wXGc33W(o*z_i-``;V= zaWd+*?8LnI40TA;bu=F`cMbxTNyv|-u`6n+=b{F*8+AA@qPFH8>K>=*Wd4@RjT&%G z)K+%D5bTXwxh1HXZbJ>=9IE^)4AlKk(bGM%DUuEM56sLd3Ndj7;yQsZ$gqshL zAG(MJp_aUnwIgcpqfmPvgX+MII&_mzzorXNhjkh1gR~1h14kYDd+7Q5|2+ZyswIsu zdzS`Pp&Dur>!D`a9<>79Q5{S~&3p!y#Z{yURzi)i4mQAO48uLx6m#`3TM~`>`(OrY;NM|&{2sN$cTp?$5!J45Ph&=FZqz^v z_jH>jFGhlvz7c9GdZP~AB-EiTFyM)k?W%jxqYRS8x2HFF)q~D^x6H8Gu{tdOa_fco! zBWeqLqRj0{kGeJaQ2n~A5YPvxBWk7tQ5C17egzkz4$(U60n{0|fchT1MV*1vy-kDp ztW{Af)(N$e18jUU>P)RbCg^tTBETO4j?1Wql0=)4W=G8^0Bd0=Y6;z_k*`I4XpW-> z@)7loPv6Jfic+Y7S3|8pOH_MZtbNe)-~aoDKm{_Up$^k2ER2^>BmW2UVurrvl$Szn zMHH&xSk!>NK@D&rY9Pl@Gku7umH8R z2e1VGifTAntT6-X8s$cHToAQl!KhDlP1HbJqE@0C>WuYAUz{4t{a0Wv32I=OEw~;v zu>%+BM8+%J5es4w9o)KWjU@qbZU={3k~MQ+pz1*0Zh2|d3V zbqT0q3tONoYVZ1?4%;ZylEqtBqZ&xC@x!S47f|JIqw2pwoduu4W`%O0;zdy9s~{`x zc6>!ZGmb^gWD#mbmZ6sH0P1)BKB|FKL(G!qLp4+$wFPxiTh$UZ^JvsoO+bC%mY}wH z4{AcUF+jinF9^6u$T`%U(u$~#8=-E&KrD^(u^OI3HJD+T=^zj_uo|dOc3ac{2BWrW zHU{B#)R*&)HR*6}o$h}T0-9kHRKxvIOF0cyaRurFbOAN6*QgcB{f$Wv#frq+V>l6;p6@*u#N;R&2emxPq8T08)0VFA2p*%s2Q$8&le7Lx*wwF zT8=aW^g~UgF7h{?qbusvPeTo0IjY{ik=%a`;1UT*@g>&6cc>3brBO~tbF77`I1g2R z8)|^Rpnd~Bp(YSK+AMJkY(abwdf^#Nj^|Kk;;N0m7|l$T@qq-LYOgWoP^Cr{%!#@- zA*e%B&Ds=o_`*a;IG4R|A}T9Iqnv`TKvoDVPaW zpb%<=rBO4gj`}XNL7nD~s9(FK)-|XBZ$>TYZq$;WK(%)jHLwS$iM&P6R!>kl?q6yG zs+b#9Fc{TwMH_F1YN!ipV0}KsCI><{v~2~aSQ>vqeIY+#AQqft8g7RAz;s2Ok&&p|F&EXrPOOP%Py@&?*`()1 z?R_Y^Rj>sC?O_z^-i}0nT!3oeD2Af%6w^=*EJnN;Y9&UYuI(JufUctk{1G*w0#nU@ z0$LY!$j77lTQ`;auS0f_1l|8vs1M6~)Y9dgW-N+or~+zbI@|cSHogv3?>y>^yvFia zZn`<7v8XdL998aH)K;yX&i&U6c95VYJdWz`)k!9!3Vs_#%| zV=?OVuSeaEgEsvHY5j}o=a>evqGnVAHG`U{ z8Mj1TyN;;u!2s02hND(+JnC$%#^QL*n({mImsCZ}qx&D{3GknMpnk=+p&CAi`Z;}w z`gtxKZ~h^)Ayy&27_~w-QHS*bYM}3}Dd(EQmkLAJ^%fmjRdq*2T%?C zhFZ$Us86WZJQL4^Iz&ZL11g1Ts4eQd&<%A>r=tdR5>@}2^$Aud{vQTlwfWqC9i}J( zTJmwIC0>APa0BX0TtyA+fsKDcb&z6#`2!^fs-wE7m1~E77>oLj%tCG1KGejHqT0K@ zfcvik&qz?mSr?kac?s&>U2M{>6w?C??DCB(zioh$0*FG`#+69R}z+EdGuLfI;@6TvewuL`=LH8KcZ%G z3k%~r)Ij`Jnk6lUC5hKY7Y;!UY=KR`jrx9MTEz;}zoP{K&2YGN7HXzzQ9m{(un0cI zAk4bj{Ig;$)E-Yk4J;nDr@K%qdIohE?^>T*|FQb6;r?snSqR8NSP#pfZovrD@AYEq zkEkD$yXe9fSOU|pHGdPTpg)4QMUu6a6Eq{&CcRe_hM{*9c#eprv-MGv>6G zM(tT+RKsC5eIV+-&p@rzMy!ZuP#vULZ_I`rh!;Y&Ga9vGb5JYv{d%`qq8&El5bAWF z!Y24TY9)d;nDhpyk#|51XejEi%|IQheW=5D3pK!`8%_DVsI9DuRWTg3vMb#L^rbqE zx`t1%G`>Rp?D}sqhpiNq|9&1pWBTKsCGqwZ}VA9Uiy&*HJ6- z3{@}JUfVFbh}S{QxF>2Qr=te47uC)&)CcIA^-nheb@U811IIpl22c&vLoIPX)M1>B zx`qo;*L58x!30#p`>e-M?VhvoyQuO{Q1w5c=l&<#Zvt6R1qz}nhS+#b)Y3P_s@NTM zidUmPSa-1&KESpZe88NY@fb$@6lx`c4w`>u(+0zdkHOBm{|^c1bl3aQ{LJ>jvcwNy zF?@?IEOf}+|2n7+J7Qg2jvB}loBs-R7?U41*RKs$AU+cHW!;a(@o!I@`&ZzI>98HD z;7qKEXHf&oc+~u!hhh=py)iGw;~4w_bkyxbI-J+A6grQY|C&x2tWSIl zR?z+bg+L=rdEDt3i0!ZqUO+8f(Vxw~1#5*ZiLb*Dbeu3VFNr#2p{OmaiQ3zys4r$0 z>i{f4d@>fm1L)SN{DXiF&pY%+=Sg!-lA=C1xlpIQw6zJUfnKPyF&)+6O4K3Vf%$WQNhE0G@u($RfjWezPy@SR)9>4On$spf8)}OJP`9HA z>dV;%)nN?kzE860%TOz_4|S_9oOYXpHzcUTlxNI$AUA4e#Zd#Sg<9gKm>fHxRxSe7 z!CLpIcp{sjKRb!pz42(`ZUM7323C#P~Ye^s2Q9_b^Mpje}zeir~Jii zMLN_>iegc$hFZbis1+N6T9GlRiA+Xq#ZuG&en5Q@-G>QiCKpf@{<1zpHT>3^@0=M> zBlIG@owXx2C*B47;11LmvcP%s0c(aD=n!<_bkxMQA`^1+ze;6Bd>Hi!K5a4_x2%8K z{D-JR_BU$4UKi|#3w8esq7G?M)JoMxtwaOVp>Byj*cSB#?Ba=Y|Dp-#o8KQbvTsp) zGZR&D6KapQp=N#p)xc@%HFOf!^Cxd8y=Nq0FmHA$jN^@Cgq?}6;|(SJgBs>(s{j5? z5r#ENE%SJhk(Y2cz2x;Y$&P2l_t;8twroc7pVC+j>R+c}J$%+3qsi~Yo1S+eZyHUT zry5~BZE0s2;lFwH{c$8E;diWt^JuUj74(g7Lwq=ICKaS%e=LaMq!qS}c482E%2F?- zP0K*J2bAHTSsk4T*Cqc64LKzcUb>%@Cfp1+(tUpVDWqMV*_r0F?Md<5ZRl+zPKor}~>Mf|F5 z?*`#kqz(71KZSy+aF@jWRQ{8U^0WiLwRA_rmhFo+|%Aegf%TOq$!V!8UNpR(xS?WcqRpvkm`6{4RO3h_A6_ZrL)8 zzv$q5n-)Ns$&}5BXbTBxg zsho@Ss&;lh#C!0bwE4o%&T1y%VKh1d2T-Ou?rI^TD($nzjiPC2^myPTp;a|f1!;7P( z?cg41RaBB^^%ouKmrc(MX1CYQa4hwj+j?aa*PJrrc>l6>{Zxr(HSZJ3yDw8=EAKoS zDMF!xxRDG!-o*2fcbo7%(tPb|lprmy4Xa$sFTx#dI4xz)5blgmZF^@GCT%D=$K8V?@dKdN($<&qmG`EybEl&1sz_n;reuV zj=Z2R>K!AT)Dvg_hp9GCPC5!F(VL17aV@^3@?7$6*~WgfCXjZQyyBGWhk9trv7P*H zNn55tGl*$~6Q6hFb+Ps5P^Sp_pWGBI$1E0OYhFD=@OuhoBfS8H;(71WP-@;kOcBRX z^0SgZ0_Tu^hV;gSv+%0TcBqGcHgWW%vl%Apm_$5}9qs-u9IDw|yn^vHkx|#wZe_ z@HUO^29kD>crnVBCa(a4TV&fhLVkYI zy*>Z?iv+IO5nZOjY1;_@;QBvLKEm%wUy3WxhX(ZAqQM?mlE!P2w~da%Y$qd$M-iUS z`=d=8K)rF4nMAxP`Tw*2lgKD%JFZHBV8UG~aFcN2bH(QWP1!M|-@_|pZlke3ZMn9# zOm%BRTX~7K5N$4^>~nR_;||mRp`o8`0~HDDnL>OgZy*ij<9$PV9XfhJUS-V9jP(>E z?-hAt3FoBz1M)hOmYMuy#LE!=hZ+);2JOeElPpo;0LorA!CP%%IMt|DzLDfwCoS{RiZK zXR0|m>8=i-;(D7opUkwx^WkjX#OE*#6thdXfyOHnK1^mf^`2Ai5cz*&AKt#C521`7 z;p%oE!Pc)(|L}5)ysCuVhiKp#fs}Nr=Nh&k{+#p>!ru|jLF1PQ-$6Yo2*0r5t@s;p zJ+F9o@_O66(@M0@L^{+{m9oA4a}u;FFWfqR2<7&nfE(e z_7nBe5gtwXE`;^yFDm`>;n&pN&)bdnjVH(apMS}JMH}Yf`*(%P%WZ@Hbasjg^>`Ok z$VvJt!qXDV}XF*bd%BnUa((YddaB`6;wJL8E|9Kk!nM##x;ng&>nF6zT^`y7yftb=Z{)BL0J5y7NYe~aviFD_!OPibQ zjQiU^dIS~dD~I)0`cDX=>OMQZ_=Cb`tUZP>}*?K zjc+6^n=N1ai+ZUjH;?xm`CrUm5%c7+jTEO+B!#xy^j*Y%B5ySV?TcaLb+l!FAl#fr zhvO@pOqnv&tIqq9wC$7&WM%4--j4V#;x}n;jXu2#sjw7hl97$D17DIko8Su4*AxGZ zcwgn&r#ut z?F5~DL*caei>)-8^akWF$DDLH5s#8ThqP+EX?c6m#%0oWl9%{=uaW zIDhqM=o5w0@h(oRfj`kmQbt`9M^LE^<@8LV;tt;Sq)#C2Eop~|$74Urb^M~^wA9Z+ z-fxus#ioCzP66VxiT|#@|4*n@o`Y0ALFREXD%#EtQrSh`O5VBT>se2JEgJZmus`9F zgf9`^M)&})o)*+gd|uO5FVZ(tKN;!al;29cH|hEH{h!WzBe66dB;$bXOvzzXsK7hL zHd@e@ElRoOG}H*wkyeT_dWtja^L8MLZy^1iZErLtqkKxLdulKYPOv+ z`upzz1>RHevu(&1cTq@B2Ew(-zd}4cl|B=m#T!RBn!Nsm>y!73>XNpZjxG`}Y3pAh zKG}9Q*ZP(^=}2$DyF~x~C-J#TAcjH_6xc_mo<+RxXgrd42;nriN}YZ2tf6cP;!ACM zYw9OHiy6pU-Y7eu0kmI>_r8sfR{xi%c$~K!;q2_)X$mNRIq!Mi0=#2rbQtNOWHcqd zl1_iYuXwYQR*rWFW&Wg$o*aaiQs!&g%}UxD-Vo9&qaS&XaTU7j@_zBujKuP4jJ%w*l@j3;j6YoU00v-KCp&aCmBtDV!GU&98%%YKjysycxM_%I7kF*fVB|c>d z{HJ!X9=<2P0qR+&-@hF+(8wn2#|&h6A^$0h=V?rSM&gw<2rSD0GLu(_+@DPmM+(y7 z2sizrm2oAE*?{%A}x` z2fV+NUfQ-eoxwe1uy;snfJ3R5m-4^jWn7HgDEpXl`*^=1?(S_H?oA{ciOVoMg=dkz z)i#`lbUhi>8F@bu?m-9M4CD^wJCOF}<43t565f%gXC7}E%Fm;m%eM7|cyjIkS0n~f za0?l?Y(sgK$(w=nvAiYhAa77632z@7tVe!*td7qplMMCbwryOu@omIMkUz$@ag_8E zHq87@rCKBuvx#}A@Gs%bcBB*VFDgB;@gQdXt1bII4W}UQ9nJiQ$A~YY{&~vYwq*{J zPO|5DLwY*uUn6ZP;gOn6idlKbW%LZ>5V3Em=Egk~xtdsy%DZXy5b<;5-ykoPGBtP` z5%%GYwp~oJimTM|rcM^r)0l7r>enD%k~hcyw(oZQK!MCOc$SPeGf)%ki9qHLc+55Jmy0rZb;b+RQ`K4)ZvNmEJ1tZD4NFhBd zaF?xEfx_L1x8^NG-ek(^5ot-AMt)k`-~^22txkFfZ%zifmvT#abKCX?k>8if$%(fj zJ-?emX$Z8Zf}T#iRVdJi0>5Kn+xR#vLE2;TGc)o-HeGezQSJ!!8{>bZJJCtIdVZl! zVd9C;2jb}{TLtHm?#@hw{v;8qQLZ52EQAZ%1}{;jv<=TDyqVW! z2lj_eFUVl`Q70R31M(A}uShSie-Mu)@dK&dNca|GZN=`y|0Zt z9zbWgcrR0L0qM&bU>94z2>AmEw<2vY;qR%VrzvTI47^3m*h>Lj*~jK$p1+Ce$v0;okpIX zKS?jHKg4=cC==c%F@}O8ZGlr1_=fbvXE1rwZ3jh3OwJxZCO)2W$7o}t&8uUrYR^Do z{hvthL%ICCdTyiV{-3oSexRW>WW1zcEFHJt?dB=^zyD_jWfGtC1bl5{O3P2)Sn5O) zeonal7iEW2?f~hTRM0+C)PIESJTWnnf=hURwKKm%Bc++i7UG?3XXOaLcG7lYZQfd>|4O`^Et`q5?%KA4&Qy3xW_JqK;caWv zZXk& zZ~}$Slkt$$WxT5h2k}nhy+gb@6&KO?eBz<*%Efj#;D! z&{t8@vEwu8FT6bGpMygrf&xF-!KluUwo!%G(oo`ahH`stIop@xDuGotEd;}D;f9F? zh&QxtyrSJ7iI-i+B zehJbqQfC40BbDdPp-$|x)(++$TSv+6@gyE0VUsNsMk8N7*J$KEY5(9%T*jN5@+XP+ zAUu`M{zE+j42}%MQ_*e)%8chNM47G_@Wo(u6YsA-#41xMnXUL6mG)CP51BRXXqDBS zxG%4s0(9P!BI4rRWqS- zbM?aGqQNGle@)@TdPfwA4ek~jo6ps~PmGHMSGWE# zF%i*mQG;Ev5m6D{;v&Lbp3=(f9pM@n7VC=c6G!p>(c!@ryT(+eqb5-iVX+amf-8*t zo)IzsN44@rQusOw`giXi72hw=8MuA^gyY_``c5f6Yxk6|x0j#V*lYWt=@XJ}@A+MJ z?^&JZFP&9k!P)Kk7kVezUS>%?=k}%AJsaBGm#hf2}<6EY1HchyZ!s(wX zen?j5{Irf1o+W7>5f>L3-6J-ka!zLpulP&3og3qm6me!w$n57FHEVxfhkN+)L-W47Zf3K+X zTX&nFIuX$kF=jwb`b30B#<@a*O9h9d(8;P9X--znu(*iG#FO>^I#@^c#kj&5V_2`a z{t;18uCV^GJt77kS)-%pkp+`h_4p>BV;t{JJ z8As`e$Y_oiTNDxdWldW2v=K{J|2=^6@!BoRJADLY$es6Oxp1=1=NN z#diG%MnuNO_dDjy7+J z=iJBi>L1-B{+}w&rSV&6Z*7tX7|eO zslYnXp^IVt?@3G;+S*ycH(_5FXYHi%b$dEfC1mLCyyBfu_iN{V?*#v7=hh_gPh*^u z(sS@#T)_U(aS<_5VJu?8z*uJ{ulUdb&PVZ82RbvymmTPw7JqY~vv`WS5izlG^cE2l z-(Zk4yE8hW#31J*XTn!QoCUlR77uei^vT2?M>+ntprWq$g`=H8U$K|n<6@4i=n?Tn zehcN>S$~nNYF`%fG()j&J!2vwyE5B^JY$?oeBuvIbiR)NJk6OU;pa)tnW>zvg!Xft z@yQZ$E^#hMlCD-{bT2xMWmn9yo><`=kt}}1250H`ryHD`)0626=Xh3&?i~>o9ud?$ zVa-P8t|a*zMcBRgzb!3?Dk`E!e6^$OMW1cXtVt7QCpdehj4yM<`Az(fN4d)>jyi{> zjt{utT$xn2J}mz11!vZTu9uy;y}XXBh#&Ervvd5--<;**Bd$8H#*e%1OrP-jnzLgP wpO(!Ua;Xx+Z#ipwC%nJwT\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." -msgstr "Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
\n" +msgstr "" +"Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
\n" "Wenn dieser Lieferant gelöscht wird, werden auch diese Zulieferer-Teile gelöscht." #: company/templates/company/detail.html:21 @@ -2034,7 +2041,7 @@ msgstr "Keine Website angegeben" msgid "Uses default currency" msgstr "verwendet Standard-Währung" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2123,13 +2130,13 @@ msgstr "Zulieferer-Teile" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "Neues Zulieferer-Teil anlegen" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "Neues Zulieferer-Teil" @@ -2227,7 +2234,7 @@ msgstr "Zuliefererteil entfernen" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "Löschen" @@ -2253,7 +2260,7 @@ msgstr "Zulieferer-Teile" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "BestandsObjekte" @@ -2267,7 +2274,7 @@ msgstr "BestandsObjekte" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "Aufträge" @@ -2279,7 +2286,7 @@ msgstr "Aufträge" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "Bestellungen" @@ -2358,7 +2365,7 @@ msgid "Pricing Information" msgstr "Preisinformationen ansehen" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "Preisstaffel hinzufügen" @@ -2468,15 +2475,15 @@ msgstr "Neues Zulieferer-Teil anlegen" msgid "Delete Supplier Part" msgstr "Zulieferer-Teil entfernen" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "neue Preisstaffel hinzufügt" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "Preisstaffel bearbeiten" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "Preisstaffel löschen" @@ -2566,7 +2573,7 @@ msgstr "Zieldatum für Auftrags-Lieferung." msgid "Enter sales order number" msgstr "Auftrag-Nummer eingeben" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "Zieldatum für Auftrags-Fertigstellung." @@ -2602,7 +2609,7 @@ msgstr "Nutzer oder Gruppe der/die für diesen Auftrag zuständig ist/sind" msgid "Order notes" msgstr "Bestell-Notizen" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "Bestellungs-Status" @@ -2643,8 +2650,8 @@ msgstr "Geplantes Lieferdatum für Auftrag." msgid "Date order was completed" msgstr "Datum an dem der Auftrag fertigstellt wurde" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -2652,120 +2659,132 @@ msgstr "Anzahl muss größer Null sein" msgid "Part supplier must match PO supplier" msgstr "Teile-Zulieferer muss dem Zulieferer der Bestellung entsprechen" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "Nur Teile aufgegebener Bestllungen können empfangen werden" -#: order/models.py:359 +#: order/models.py:348 +#, fuzzy +#| msgid "Quantity must be integer" +msgid "Quantity must be an integer" +msgstr "Anzahl muss eine Ganzzahl sein" + +#: order/models.py:350 +#, fuzzy +#| msgid "Quantity must be positive" +msgid "Quantity must be a positive number" +msgstr "Anzahl muss positiv sein" + +#: order/models.py:369 msgid "Received items" msgstr "Elemente empfangen" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "Firma an die die Teile verkauft werden" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "Kundenreferenz" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "Bestellreferenz" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "Versanddatum" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "Versand von" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "Bestellung kann nicht versendet werden weil er nicht anhängig ist" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "Anzahl" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "Position - Referenz" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "Position - Notizen" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "Bestellung" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "Bestellung" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "Zulieferer-Teil" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "Empfangen" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "Empfangene Objekt-Anzahl" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "Preis" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "Preis pro Einheit" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "BestandsObjekt wurde nicht zugewiesen" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "Kann BestandsObjekt keiner Zeile mit einem anderen Teil hinzufügen" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "Kann BestandsObjekt keiner Zeile ohne Teil hinzufügen" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "Die zugeordnete Anzahl darf nicht die verfügbare Anzahl überschreiten" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "Anzahl für BestandsObjekt mit Seriennummer muss 1 sein" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "Position" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "Position" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "BestandsObjekt für Zuordnung auswählen" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "Anzahl für Bestandszuordnung eingeben" @@ -2813,9 +2832,24 @@ msgstr "Bestellstatus" msgid "Issued" msgstr "Aufgegeben" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "Neuer Lagerort" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "Neuen Lagerort anlegen" + +#: order/templates/order/order_cancel.html:8 +#, fuzzy +#| msgid "Cancelling this order means that the order will no longer be editable." +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar ist." #: order/templates/order/order_complete.html:7 @@ -2827,10 +2861,12 @@ msgid "This order has line items which have not been marked as received." msgstr "Diese Bestellung enthält Positionen, die nicht als empfangen markiert wurden." #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." -msgstr "Wenn Sie diese Bestellung als abgeschlossen markieren, werden diese Positionen entfernt." +#, fuzzy +#| msgid "Cancelling this order means that the order will no longer be editable." +msgid "Completing this order means that the order and line items will no longer be editable." +msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar ist." -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "Nachdem diese Bestellung plaziert ist können die Positionen nicht länger bearbeitbar ist." @@ -2882,11 +2918,15 @@ msgid "Select Purchase Order" msgstr "Bestellung auswählen" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" -msgstr "Neue Bestellung für {{ supplier.name }} anlegen" +#, fuzzy, python-format +#| msgid "Create new purchase order" +msgid "Create new purchase order for %(name)s" +msgstr "Neue Bestellung anlegen" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, fuzzy, python-format +#| msgid "Select a purchase order for" +msgid "Select a purchase order for %(name)s" msgstr "Bestellung auswählen für" #: order/templates/order/po_attachments.html:12 @@ -2908,43 +2948,29 @@ msgid "Purchase Order Items" msgstr "Bestellungs-Positionen" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "Position hinzufügen" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "Neuer Lagerort" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "Neuen Lagerort anlegen" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "Keine Positionen gefunden" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "Stück-Preis" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "Position bearbeiten" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "Position löschen" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "Position empfangen" @@ -2967,7 +2993,7 @@ msgstr "Ausstehende Teile für %(order)s - %(desc)s empfangen" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "Teile" @@ -3020,6 +3046,10 @@ msgstr "Kundenreferenz" msgid "Warning" msgstr "Warnung" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar ist." + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "Auftrags-Positionen" @@ -3214,65 +3244,65 @@ msgstr "Anzahl kleiner null empfangen" msgid "No lines specified" msgstr "Keine Zeilen angegeben" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "{n} Teile bestellt" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "Zulieferer-Teil muss ausgewählt werden" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "Zulieferer muss zu Teil und Bestellung passen" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "Position bearbeiten" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "Position löschen" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "Position gelöscht" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "Seriennummern zuweisen" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "{n} Positionen zugeordnet" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "Position auswählen" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "Kein passends Teil für Seriennummer gefunden" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "ist nicht auf Lager" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "bereits einem Auftrag zugeordnet" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "Lagerbestand dem Auftrag zuweisen" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "Zuordnung bearbeiten" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "Zuordnung entfernen" @@ -3458,7 +3488,7 @@ msgstr "Teil-Kategorie" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "Teil-Kategorien" @@ -4005,7 +4035,7 @@ msgstr "Neuen Bauauftrag beginnen" msgid "All parts" msgstr "Alle Teile" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "Teil-Kategorie anlegen" @@ -4695,63 +4725,63 @@ msgstr "Teil wurde gelöscht" msgid "Part Pricing" msgstr "Teilbepreisung" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "Teilparametervorlage bearbeiten" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "Teilparametervorlage löschen" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "Teilparameter anlegen" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "Teilparameter bearbeiten" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "Teilparameter löschen" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "Teil-Kategorie bearbeiten" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "Teil-Kategorie löschen" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "Teil-Kategorie wurde gelöscht" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "Kategorieparametervorlage anlegen" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "Kategorieparametervorlage bearbeiten" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "Kategorieparametervorlage löschen" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "Stücklisten-Position anlegen" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "Stücklisten-Position bearbeiten" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "löschen von Stücklisten-Position bestätigen" @@ -5302,15 +5332,15 @@ msgid "Stock adjustment actions" msgstr "Bestands-Anpassungs Aktionen" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "Bestand zählen" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "Bestand hinzufügen" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "Bestand entfernen" @@ -5504,7 +5534,7 @@ msgid "Stock Details" msgstr "Objekt-Details" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "Bestand-Lagerorte" @@ -5690,7 +5720,7 @@ msgstr "Entfernen" msgid "Add Stock Items" msgstr "BestandsObjekte hinzufügen" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "Hinzufügen" @@ -5868,6 +5898,40 @@ msgstr "an Kunde versand" msgid "No stock location set" msgstr "Kein Lagerort gesetzt" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "Anzeige-Einstellungen" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "Farbschemata" + +#: templates/InvenTree/settings/appearance.html:29 +#, fuzzy, python-format +#| msgid "" +#| "\n" +#| "\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +#| "\t\tPlease select another color theme :)\n" +#| "\t" +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" +"\n" +"\t\tDie CSS Datei \"%(invalid_color_theme)s.css\" für das aktuell ausgewählte Farbschema wurde nicht gefunden.
\n" +"\t\tBitte ein anderes Farbschema auswählen:)\n" +"\t" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "Bauauftrag-Einstellungen" @@ -5951,7 +6015,7 @@ msgstr "Auftrags-Einstellungen" msgid "Stock Settings" msgstr "Bestands-Einstellungen" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "Stock-Optionen" @@ -5965,8 +6029,8 @@ msgid "Account" msgstr "Konto" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" -msgstr "Thema" +msgid "Appearance" +msgstr "" #: templates/InvenTree/settings/tabs.html:13 msgid "InvenTree Settings" @@ -5984,25 +6048,6 @@ msgstr "Bericht" msgid "Categories" msgstr "Kategorien" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "Anzeige-Einstellungen" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "Farbschemata" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "\n" -"\t\tDie CSS Datei \"%(invalid_color_theme)s.css\" für das aktuell ausgewählte Farbschema wurde nicht gefunden.
\n" -"\t\tBitte ein anderes Farbschema auswählen:)\n" -"\t" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "Benutzerinformation" @@ -6065,13 +6110,23 @@ msgid "View Code on GitHub" msgstr "Code auf GitHub ansehen" #: templates/about.html:63 -msgid "Get the App" -msgstr "App herunterladen" +msgid "Credits" +msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "Fehlerbericht senden" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "Schliessen" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "Anhang hinzufügen" @@ -6267,7 +6322,7 @@ msgid "Quantity Per" msgstr "Anzahl pro" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "Bestand bestellen" @@ -6400,11 +6455,6 @@ msgstr "Lade Daten" msgid "Submit" msgstr "Abschicken" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "Schliessen" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "ungültige Antwort vom Server" @@ -6978,6 +7028,10 @@ msgstr "Alle" msgid "Form errors exist" msgstr "Fehler in Formular" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "Kaufen" @@ -6990,7 +7044,7 @@ msgstr "Verkaufen" msgid "Scan Barcode" msgstr "Barcode scannen" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "Admin" @@ -7122,43 +7176,43 @@ msgstr "Barcode Aktionen" msgid "Print test reports" msgstr "Test-Berichte drucken" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "Zu ausgewählten BestandsObjekten hinzufügen" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "Von ausgewählten BestandsObjekten entfernen" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "Inventur für gewählte BestandsObjekte" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "Ausgewählte BestandsObjekte verschieben" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "Bestand verschieben" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "Ausgewählte Positionen bestellen" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "Status ändern" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "Bestandsstatus ändern" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "Ausgewählte Positionen löschen" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "Bestand löschen" @@ -7194,34 +7248,46 @@ msgstr "Berechtigungen" msgid "Important dates" msgstr "wichtige Daten" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "Berechtigung geändert" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "Gruppe" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "Ansicht" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "Berechtigung Einträge anzuzeigen" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "Berechtigung Einträge zu erstellen" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "Ändern" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "Berechtigungen Einträge zu ändern" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "Berechtigung Einträge zu löschen" + +#~ msgid "Marking this order as complete will remove these line items." +#~ msgstr "Wenn Sie diese Bestellung als abgeschlossen markieren, werden diese Positionen entfernt." + +#~ msgid "Create new purchase order for {{ supplier.name }}" +#~ msgstr "Neue Bestellung für {{ supplier.name }} anlegen" + +#~ msgid "Theme" +#~ msgstr "Thema" + +#~ msgid "Get the App" +#~ msgstr "App herunterladen" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 14192c38d6..097f4c0f8c 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-14 11:13+0000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -34,10 +34,10 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:99 build/forms.py:120 -#: build/forms.py:142 build/forms.py:166 build/forms.py:188 build/forms.py:223 +#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 -#: order/forms.py:71 part/forms.py:132 +#: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "" @@ -49,7 +49,7 @@ msgstr "" msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:76 +#: InvenTree/forms.py:159 templates/registration/login.html:77 msgid "Enter password" msgstr "" @@ -73,40 +73,41 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:361 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:364 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:385 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:389 InvenTree/helpers.py:392 InvenTree/helpers.py:395 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:400 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:408 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:412 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1659 +#: InvenTree/models.py:59 stock/models.py:1662 msgid "Attachment" msgstr "" @@ -122,9 +123,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1888 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:964 +#: templates/js/stock.js:1041 msgid "User" msgstr "" @@ -133,30 +134,33 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2029 part/templates/part/params.html:27 -#: report/models.py:179 templates/InvenTree/search.html:136 -#: templates/InvenTree/search.html:273 templates/js/part.js:109 +#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: report/models.py:179 templates/InvenTree/search.html:137 +#: templates/InvenTree/search.html:289 templates/js/part.js:110 +#: templates/js/part.js:553 templates/js/stock.js:944 msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:365 -#: company/templates/company/detail.html:26 -#: company/templates/company/supplier_part_base.html:70 +#: build/templates/build/detail.html:21 company/models.py:342 +#: company/models.py:494 company/templates/company/detail.html:27 +#: company/templates/company/manufacturer_part_base.html:72 +#: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 #: report/templates/report/inventree_build_order_base.html:118 -#: templates/InvenTree/search.html:143 templates/InvenTree/search.html:208 -#: templates/InvenTree/search.html:280 +#: templates/InvenTree/search.html:144 templates/InvenTree/search.html:224 +#: templates/InvenTree/search.html:296 #: templates/InvenTree/settings/header.html:9 templates/js/bom.js:190 -#: templates/js/build.js:677 templates/js/build.js:944 +#: templates/js/build.js:736 templates/js/build.js:1004 #: templates/js/company.js:56 templates/js/order.js:183 -#: templates/js/order.js:280 templates/js/part.js:168 templates/js/part.js:251 -#: templates/js/part.js:370 templates/js/part.js:566 templates/js/stock.js:554 -#: templates/js/stock.js:938 +#: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 +#: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 +#: templates/js/stock.js:554 templates/js/stock.js:956 +#: templates/js/stock.js:1015 msgid "Description" msgstr "" @@ -168,92 +172,92 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:480 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:481 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:482 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:483 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:484 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" -#: InvenTree/status.py:84 +#: InvenTree/status.py:93 msgid "Background worker check failed" msgstr "" -#: InvenTree/status.py:88 +#: InvenTree/status.py:97 msgid "Email backend not configured" msgstr "" -#: InvenTree/status.py:91 +#: InvenTree/status.py:100 msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:94 InvenTree/status_codes.py:135 -#: InvenTree/status_codes.py:228 +#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 +#: InvenTree/status_codes.py:236 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:95 +#: InvenTree/status_codes.py:103 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:231 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:97 InvenTree/status_codes.py:137 -#: InvenTree/status_codes.py:230 +#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:238 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:98 InvenTree/status_codes.py:138 -#: InvenTree/status_codes.py:180 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 +#: InvenTree/status_codes.py:188 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:99 InvenTree/status_codes.py:139 -#: InvenTree/status_codes.py:182 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:190 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:136 +#: InvenTree/status_codes.py:144 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:176 +#: InvenTree/status_codes.py:184 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:177 +#: InvenTree/status_codes.py:185 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:178 +#: InvenTree/status_codes.py:186 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:179 +#: InvenTree/status_codes.py:187 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:181 +#: InvenTree/status_codes.py:189 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:229 +#: InvenTree/status_codes.py:237 msgid "Production" msgstr "" @@ -312,7 +316,7 @@ msgstr "" msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:85 +#: InvenTree/views.py:887 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -356,138 +360,150 @@ msgstr "" msgid "Barcode associated with StockItem" msgstr "" -#: build/forms.py:34 +#: build/forms.py:37 msgid "Build Order reference" msgstr "" -#: build/forms.py:35 +#: build/forms.py:38 msgid "Order target date" msgstr "" -#: build/forms.py:39 build/templates/build/build_base.html:104 +#: build/forms.py:42 build/templates/build/build_base.html:136 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 #: order/templates/order/sales_order_base.html:117 #: report/templates/report/inventree_build_order_base.html:126 -#: templates/js/build.js:723 templates/js/order.js:200 +#: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 msgid "Target Date" msgstr "" -#: build/forms.py:40 build/models.py:224 -msgid "" -"Target date for build completion. Build will be overdue after this date." +#: build/forms.py:43 build/models.py:224 +msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:45 build/forms.py:87 build/forms.py:257 build/models.py:1103 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:91 -#: build/templates/build/detail.html:31 common/models.py:696 -#: company/forms.py:131 company/templates/company/supplier_part_pricing.html:77 +#: build/templates/build/build_base.html:123 +#: build/templates/build/detail.html:31 common/models.py:703 +#: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:193 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:340 -#: part/forms.py:369 part/forms.py:385 part/models.py:2158 +#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2178 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:12 -#: part/templates/part/part_pricing.html:19 +#: part/templates/part/part_pricing.html:11 +#: part/templates/part/part_pricing.html:18 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1563 -#: stock/templates/stock/item_base.html:51 -#: stock/templates/stock/item_base.html:57 -#: stock/templates/stock/item_base.html:240 +#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 +#: stock/templates/stock/item_base.html:244 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 -#: templates/js/bom.js:205 templates/js/build.js:420 templates/js/build.js:954 -#: templates/js/stock.js:956 templates/js/stock.js:1194 +#: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 +#: templates/js/stock.js:1033 templates/js/stock.js:1271 msgid "Quantity" msgstr "" -#: build/forms.py:46 +#: build/forms.py:49 msgid "Number of items to build" msgstr "" -#: build/forms.py:88 +#: build/forms.py:91 msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:92 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 msgid "Serial Numbers" msgstr "" -#: build/forms.py:94 +#: build/forms.py:97 msgid "Enter serial numbers for build outputs" msgstr "" -#: build/forms.py:100 +#: build/forms.py:103 msgid "Confirm creation of build output" msgstr "" -#: build/forms.py:121 +#: build/forms.py:124 msgid "Confirm deletion of build output" msgstr "" -#: build/forms.py:142 +#: build/forms.py:145 msgid "Confirm unallocation of stock" msgstr "" -#: build/forms.py:166 +#: build/forms.py:169 msgid "Confirm stock allocation" msgstr "" -#: build/forms.py:189 +#: build/forms.py:186 msgid "Mark build as complete" msgstr "" -#: build/forms.py:213 build/templates/build/auto_allocate.html:18 +#: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:270 +#: stock/templates/stock/item_base.html:274 #: stock/templates/stock/stock_adjust.html:17 -#: templates/InvenTree/search.html:244 templates/js/barcode.js:363 -#: templates/js/barcode.js:531 templates/js/build.js:434 +#: templates/InvenTree/search.html:260 templates/js/barcode.js:363 +#: templates/js/barcode.js:531 templates/js/build.js:490 #: templates/js/stock.js:641 msgid "Location" msgstr "" -#: build/forms.py:214 +#: build/forms.py:211 msgid "Location of completed parts" msgstr "" -#: build/forms.py:219 -msgid "Confirm incomplete" +#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/templates/build/detail.html:59 order/models.py:455 +#: order/templates/order/receive_parts.html:24 +#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: templates/js/barcode.js:119 templates/js/build.js:770 +#: templates/js/order.js:187 templates/js/order.js:285 +#: templates/js/stock.js:628 templates/js/stock.js:1279 +msgid "Status" msgstr "" -#: build/forms.py:220 -msgid "Confirm completion with incomplete stock allocation" +#: build/forms.py:216 +msgid "Build output stock status" msgstr "" #: build/forms.py:223 +msgid "Confirm incomplete" +msgstr "" + +#: build/forms.py:224 +msgid "Confirm completion with incomplete stock allocation" +msgstr "" + +#: build/forms.py:227 msgid "Confirm build completion" msgstr "" -#: build/forms.py:243 +#: build/forms.py:252 msgid "Confirm cancel" msgstr "" -#: build/forms.py:243 build/views.py:66 +#: build/forms.py:252 build/views.py:66 msgid "Confirm build cancellation" msgstr "" -#: build/forms.py:257 +#: build/forms.py:266 msgid "Select quantity of stock to allocate" msgstr "" -#: build/models.py:65 build/templates/build/build_base.html:8 -#: build/templates/build/build_base.html:35 +#: build/models.py:65 build/templates/build/build_base.html:9 +#: build/templates/build/build_base.html:63 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -497,9 +513,9 @@ msgstr "" #: build/templates/build/index.html:15 order/templates/order/so_builds.html:12 #: order/templates/order/so_navbar.html:19 #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 -#: part/templates/part/navbar.html:58 templates/InvenTree/index.html:182 -#: templates/InvenTree/search.html:169 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 +#: templates/InvenTree/search.html:185 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -507,12 +523,12 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:188 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2167 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 -#: templates/js/build.js:509 templates/js/build.js:948 +#: templates/js/build.js:565 templates/js/build.js:1008 msgid "Reference" msgstr "" @@ -520,7 +536,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:121 +#: build/models.py:146 build/templates/build/build_base.html:153 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -530,28 +546,27 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:86 -#: build/templates/build/detail.html:26 company/models.py:539 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/build_base.html:118 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1856 part/models.py:1868 part/models.py:1886 -#: part/models.py:1961 part/models.py:2057 part/models.py:2142 -#: part/templates/part/part_app_base.html:7 -#: part/templates/part/part_pricing.html:15 part/templates/part/related.html:29 +#: part/models.py:1876 part/models.py:1888 part/models.py:1906 +#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: part/templates/part/part_app_base.html:8 +#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 -#: part/templates/part/subcategories.html:17 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 #: report/templates/report/inventree_so_report.html:90 -#: templates/InvenTree/search.html:111 templates/InvenTree/search.html:194 +#: templates/InvenTree/search.html:112 templates/InvenTree/search.html:210 #: templates/js/barcode.js:362 templates/js/bom.js:163 -#: templates/js/build.js:681 templates/js/build.js:921 -#: templates/js/company.js:138 templates/js/part.js:232 -#: templates/js/part.js:337 templates/js/stock.js:523 -#: templates/js/stock.js:1266 +#: templates/js/build.js:741 templates/js/build.js:981 +#: templates/js/company.js:140 templates/js/company.js:238 +#: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 +#: templates/js/stock.js:1343 msgid "Part" msgstr "" @@ -572,9 +587,7 @@ msgid "Source Location" msgstr "" #: build/models.py:178 -msgid "" -"Select location to take stock from for this build (leave blank to take from " -"any stock location)" +msgid "Select location to take stock from for this build (leave blank to take from any stock location)" msgstr "" #: build/models.py:183 @@ -601,7 +614,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:159 +#: build/models.py:204 part/templates/part/part_base.html:160 msgid "Build Status" msgstr "" @@ -609,7 +622,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:430 +#: build/models.py:212 stock/models.py:432 msgid "Batch Code" msgstr "" @@ -622,11 +635,11 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" -#: build/models.py:227 order/models.py:218 +#: build/models.py:227 order/models.py:218 templates/js/build.js:788 msgid "Completion Date" msgstr "" @@ -642,7 +655,7 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:142 +#: build/models.py:250 build/templates/build/build_base.html:174 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 #: order/templates/order/sales_order_base.html:138 part/models.py:886 @@ -655,33 +668,35 @@ msgid "User responsible for this build order" msgstr "" #: build/models.py:256 build/templates/build/detail.html:91 -#: company/templates/company/supplier_part_base.html:77 +#: company/templates/company/manufacturer_part_base.html:79 +#: company/templates/company/manufacturer_part_detail.html:28 +#: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:100 -#: stock/models.py:424 stock/templates/stock/item_base.html:330 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 +#: stock/models.py:426 stock/templates/stock/item_base.html:334 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:426 +#: build/models.py:257 part/models.py:744 stock/models.py:428 msgid "Link to external URL" msgstr "" -#: build/models.py:261 build/templates/build/navbar.html:59 -#: company/models.py:133 company/models.py:372 -#: company/templates/company/navbar.html:59 -#: company/templates/company/navbar.html:62 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: build/models.py:261 build/templates/build/navbar.html:53 +#: company/models.py:135 company/models.py:501 +#: company/templates/company/navbar.html:70 +#: company/templates/company/navbar.html:73 order/models.py:123 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:227 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:122 +#: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:496 stock/models.py:1555 stock/models.py:1665 +#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:329 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -689,141 +704,152 @@ msgstr "" msgid "Extra build notes" msgstr "" -#: build/models.py:673 +#: build/models.py:739 msgid "No build output specified" msgstr "" -#: build/models.py:676 +#: build/models.py:742 msgid "Build output is already completed" msgstr "" -#: build/models.py:679 +#: build/models.py:745 msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:754 +#: build/models.py:838 msgid "Completed build output" msgstr "" -#: build/models.py:996 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1018 -msgid "Build item must specify a build output" +#: build/models.py:1157 +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1023 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1027 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1034 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1038 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1042 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1082 stock/templates/stock/item_base.html:302 -#: templates/InvenTree/search.html:167 templates/js/build.js:655 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1083 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1090 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:89 -#: stock/templates/stock/item_base.html:324 -#: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:771 -#: templates/js/stock.js:927 templates/js/stock.js:1185 +#: stock/templates/stock/item_base.html:93 +#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 +#: templates/js/stock.js:1004 templates/js/stock.js:1262 msgid "Stock Item" msgstr "" -#: build/models.py:1091 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1104 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1112 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1113 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" +#: build/templates/build/allocate.html:7 +msgid "Allocate Parts" +msgstr "" + #: build/templates/build/allocate.html:15 -msgid "Incomplete Build Ouputs" +msgid "Allocate Stock to Build" msgstr "" -#: build/templates/build/allocate.html:21 -msgid "Build order has been completed" +#: build/templates/build/allocate.html:22 +msgid "Allocate stock to build" msgstr "" -#: build/templates/build/allocate.html:26 -msgid "Create new build output" +#: build/templates/build/allocate.html:23 +msgid "Auto Allocate" msgstr "" -#: build/templates/build/allocate.html:27 -msgid "Create New Output" +#: build/templates/build/allocate.html:25 templates/js/build.js:646 +msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:30 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 +msgid "Unallocate Stock" +msgstr "" + +#: build/templates/build/allocate.html:29 msgid "Order required parts" msgstr "" -#: build/templates/build/allocate.html:31 -#: company/templates/company/detail_part.html:31 order/views.py:794 +#: build/templates/build/allocate.html:30 +#: company/templates/company/detail_manufacturer_part.html:33 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" -#: build/templates/build/allocate.html:34 templates/js/build.js:590 -msgid "Unallocate stock" +#: build/templates/build/allocate.html:36 +msgid "Untracked stock has been fully allocated for this Build Order" msgstr "" -#: build/templates/build/allocate.html:35 build/views.py:338 build/views.py:784 -msgid "Unallocate Stock" +#: build/templates/build/allocate.html:40 +msgid "Untracked stock has not been fully allocated for this Build Order" msgstr "" -#: build/templates/build/allocate.html:49 -msgid "Create a new build output" +#: build/templates/build/allocate.html:47 +msgid "This Build Order does not have any associated untracked BOM items" msgstr "" -#: build/templates/build/allocate.html:50 -msgid "No incomplete build outputs remain." -msgstr "" - -#: build/templates/build/allocate.html:51 -msgid "Create a new build output using the button above" +#: build/templates/build/allocation_card.html:21 +#: build/templates/build/complete_output.html:46 +#: order/templates/order/sales_order_detail.html:75 +#: order/templates/order/sales_order_detail.html:157 +#: report/templates/report/inventree_test_report_base.html:75 +#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: templates/js/build.js:474 +msgid "Serial Number" msgstr "" #: build/templates/build/attachments.html:12 -#: build/templates/build/navbar.html:49 build/templates/build/navbar.html:52 +#: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:113 -#: part/templates/part/navbar.html:116 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 +#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -833,8 +859,7 @@ msgid "Automatically Allocate Stock" msgstr "" #: build/templates/build/auto_allocate.html:10 -msgid "" -"The following stock items will be allocated to the specified build output" +msgid "The following stock items will be allocated to the specified build output" msgstr "" #: build/templates/build/auto_allocate.html:37 @@ -845,112 +870,153 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:14 -msgid "This Build Order is allocated to Sales Order" +#: build/templates/build/build_base.html:16 +#, python-format +msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:19 -msgid "This Build Order is a child of Build Order" +#: build/templates/build/build_base.html:22 +#, python-format +msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:37 +#: build/templates/build/build_base.html:31 +msgid "Build Order is ready to mark as completed" +msgstr "" + +#: build/templates/build/build_base.html:36 +msgid "Build Order cannot be completed as outstanding outputs remain" +msgstr "" + +#: build/templates/build/build_base.html:41 +msgid "Required build quantity has not yet been completed" +msgstr "" + +#: build/templates/build/build_base.html:46 +msgid "Stock has not been fully allocated to this Build Order" +msgstr "" + +#: build/templates/build/build_base.html:65 #: company/templates/company/company_base.html:40 -#: company/templates/company/supplier_part_base.html:25 +#: company/templates/company/manufacturer_part_base.html:25 +#: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:14 part/templates/part/part_base.html:28 -#: stock/templates/stock/item_base.html:114 -#: stock/templates/stock/location.html:24 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 +#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:43 -#: build/templates/build/build_base.html:108 +#: build/templates/build/build_base.html:71 +#: build/templates/build/build_base.html:140 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:218 templates/js/table_filters.js:237 -#: templates/js/table_filters.js:254 +#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 +#: templates/js/table_filters.js:276 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:52 +#: build/templates/build/build_base.html:80 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:56 +#: build/templates/build/build_base.html:84 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:62 -msgid "Build actions" -msgstr "" - -#: build/templates/build/build_base.html:66 -msgid "Edit Build" -msgstr "" - -#: build/templates/build/build_base.html:68 -#: build/templates/build/build_base.html:176 +#: build/templates/build/build_base.html:90 +#: build/templates/build/build_base.html:215 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:69 -#: build/templates/build/build_base.html:167 build/views.py:57 +#: build/templates/build/build_base.html:95 +msgid "Build actions" +msgstr "" + +#: build/templates/build/build_base.html:99 +msgid "Edit Build" +msgstr "" + +#: build/templates/build/build_base.html:101 +#: build/templates/build/build_base.html:199 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:82 +#: build/templates/build/build_base.html:114 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:96 -#: build/templates/build/detail.html:59 order/models.py:445 -#: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:376 templates/InvenTree/search.html:236 -#: templates/js/barcode.js:119 templates/js/build.js:710 -#: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1202 -msgid "Status" +#: build/templates/build/build_base.html:140 +#, python-format +msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:108 -msgid "This build was due on" -msgstr "" - -#: build/templates/build/build_base.html:115 +#: build/templates/build/build_base.html:147 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/build_base.html:160 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:264 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:135 +#: build/templates/build/build_base.html:167 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" +#: build/templates/build/build_base.html:207 +msgid "Incomplete Outputs" +msgstr "" + +#: build/templates/build/build_base.html:208 +msgid "Build Order cannot be completed as incomplete build outputs remain" +msgstr "" + #: build/templates/build/build_children.html:10 -#: build/templates/build/navbar.html:42 +#: build/templates/build/navbar.html:36 msgid "Child Build Orders" msgstr "" -#: build/templates/build/build_output.html:10 -#: build/templates/build/navbar.html:35 build/templates/build/navbar.html:38 -msgid "Build Outputs" +#: build/templates/build/build_output.html:15 +msgid "Incomplete Build Outputs" +msgstr "" + +#: build/templates/build/build_output.html:22 +msgid "Create new build output" +msgstr "" + +#: build/templates/build/build_output.html:23 +msgid "Create New Output" +msgstr "" + +#: build/templates/build/build_output.html:36 +msgid "Create a new build output" +msgstr "" + +#: build/templates/build/build_output.html:37 +msgid "No incomplete build outputs remain." +msgstr "" + +#: build/templates/build/build_output.html:38 +msgid "Create a new build output using the button above" +msgstr "" + +#: build/templates/build/build_output.html:49 +msgid "Completed Build Outputs" msgstr "" #: build/templates/build/build_output_create.html:7 @@ -978,11 +1044,11 @@ msgid "Are you sure you wish to cancel this build?" msgstr "" #: build/templates/build/complete.html:8 -msgid "Build can be completed" +msgid "Build Order is complete" msgstr "" #: build/templates/build/complete.html:12 -msgid "Build cannot be completed" +msgid "Build Order is incomplete" msgstr "" #: build/templates/build/complete.html:15 @@ -993,19 +1059,23 @@ msgstr "" msgid "Required build quantity has not been completed" msgstr "" -#: build/templates/build/complete_output.html:9 -msgid "Stock allocation is complete" +#: build/templates/build/complete.html:21 +msgid "Required stock has not been fully allocated" msgstr "" -#: build/templates/build/complete_output.html:13 +#: build/templates/build/complete_output.html:10 +msgid "Stock allocation is complete for this output" +msgstr "" + +#: build/templates/build/complete_output.html:14 msgid "Stock allocation is incomplete" msgstr "" -#: build/templates/build/complete_output.html:19 -msgid "parts have not been fully allocated" +#: build/templates/build/complete_output.html:20 +msgid "tracked parts have not been fully allocated" msgstr "" -#: build/templates/build/complete_output.html:40 +#: build/templates/build/complete_output.html:41 msgid "The following items will be created" msgstr "" @@ -1014,11 +1084,13 @@ msgid "Select a stock item to allocate to the selected build output" msgstr "" #: build/templates/build/create_build_item.html:11 -msgid "The allocated stock will be installed into the following build output:" +#, python-format +msgid "The allocated stock will be installed into the following build output:
%(output)s" msgstr "" -#: build/templates/build/create_build_item.html:19 -msgid "No stock available for" +#: build/templates/build/create_build_item.html:17 +#, python-format +msgid "No stock available for %(part)s" msgstr "" #: build/templates/build/delete_build_item.html:8 @@ -1046,15 +1118,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:288 templates/js/stock.js:636 -#: templates/js/stock.js:1209 templates/js/table_filters.js:85 -#: templates/js/table_filters.js:179 +#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 +#: templates/js/stock.js:1286 templates/js/table_filters.js:107 +#: templates/js/table_filters.js:201 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:718 +#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1062,8 +1134,7 @@ msgstr "" msgid "No target date set" msgstr "" -#: build/templates/build/detail.html:132 templates/js/build.js:696 -#: templates/js/build.js:728 +#: build/templates/build/detail.html:132 templates/js/build.js:756 msgid "Completed" msgstr "" @@ -1075,7 +1146,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:657 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1106,20 +1177,20 @@ msgstr "" msgid "Details" msgstr "" -#: build/templates/build/navbar.html:20 build/templates/build/navbar.html:23 -#: build/templates/build/parts.html:11 -msgid "Required Parts" +#: build/templates/build/navbar.html:21 build/templates/build/navbar.html:24 +#: build/views.py:91 +msgid "Allocate Stock" msgstr "" -#: build/templates/build/navbar.html:27 build/templates/build/navbar.html:30 -msgid "In Progress" +#: build/templates/build/navbar.html:29 build/templates/build/navbar.html:32 +msgid "Build Outputs" msgstr "" -#: build/templates/build/navbar.html:45 +#: build/templates/build/navbar.html:39 msgid "Child Builds" msgstr "" -#: build/templates/build/navbar.html:56 +#: build/templates/build/navbar.html:50 msgid "Build Order Notes" msgstr "" @@ -1137,7 +1208,7 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:454 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1154,149 +1225,153 @@ msgstr "" msgid "Build was cancelled" msgstr "" -#: build/views.py:91 -msgid "Allocate Stock" -msgstr "" - -#: build/views.py:154 build/views.py:314 build/views.py:485 -msgid "Build output must be specified" -msgstr "" - -#: build/views.py:168 +#: build/views.py:138 msgid "Allocated stock to build output" msgstr "" -#: build/views.py:180 +#: build/views.py:150 msgid "Create Build Output" msgstr "" -#: build/views.py:203 stock/models.py:966 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:212 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:278 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:299 build/views.py:383 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:300 build/views.py:384 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:312 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:326 +#: build/views.py:295 build/views.py:496 +msgid "Build output must be specified" +msgstr "" + +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:408 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:414 -msgid "Build order cannot be completed" +#: build/views.py:411 +msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:425 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:441 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:476 +#: build/views.py:480 +msgid "Invalid stock status value selected" +msgstr "" + +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:573 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:711 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:732 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:765 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:774 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:789 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:801 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:844 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:850 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:851 templates/js/bom.js:230 templates/js/build.js:519 -#: templates/js/build.js:778 templates/js/build.js:961 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 +#: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:853 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1016 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1020 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1049 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1062 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1098 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1108 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1118 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1123 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1308,335 +1383,343 @@ msgstr "" msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 company/models.py:95 company/models.py:96 -msgid "Company name" +#: common/models.py:62 +msgid "Use instance name" msgstr "" #: common/models.py:63 +msgid "Use the instance name in the title-bar" +msgstr "" + +#: common/models.py:69 company/models.py:97 company/models.py:98 +msgid "Company name" +msgstr "" + +#: common/models.py:70 msgid "Internal company name" msgstr "" -#: common/models.py:68 +#: common/models.py:75 msgid "Base URL" msgstr "" -#: common/models.py:69 +#: common/models.py:76 msgid "Base URL for server instance" msgstr "" -#: common/models.py:75 +#: common/models.py:82 msgid "Default Currency" msgstr "" -#: common/models.py:76 +#: common/models.py:83 msgid "Default currency" msgstr "" -#: common/models.py:82 +#: common/models.py:89 msgid "Download from URL" msgstr "" -#: common/models.py:83 +#: common/models.py:90 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:89 +#: common/models.py:96 msgid "Barcode Support" msgstr "" -#: common/models.py:90 +#: common/models.py:97 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:96 +#: common/models.py:103 msgid "IPN Regex" msgstr "" -#: common/models.py:97 +#: common/models.py:104 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:101 +#: common/models.py:108 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:102 +#: common/models.py:109 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:115 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:116 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:115 +#: common/models.py:122 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:116 +#: common/models.py:123 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:122 +#: common/models.py:129 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:123 +#: common/models.py:130 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:136 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:130 +#: common/models.py:137 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:143 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:137 +#: common/models.py:144 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:150 msgid "Recent Part Count" msgstr "" -#: common/models.py:144 +#: common/models.py:151 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:150 part/models.py:2059 part/templates/part/detail.html:160 +#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:288 +#: templates/js/table_filters.js:310 msgid "Template" msgstr "" -#: common/models.py:151 +#: common/models.py:158 msgid "Parts are templates by default" msgstr "" -#: common/models.py:157 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:101 templates/js/table_filters.js:300 +#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 msgid "Assembly" msgstr "" -#: common/models.py:158 +#: common/models.py:165 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:164 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:304 +#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:326 msgid "Component" msgstr "" -#: common/models.py:165 +#: common/models.py:172 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:171 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:172 +#: common/models.py:179 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:178 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:312 +#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:334 msgid "Salable" msgstr "" -#: common/models.py:179 +#: common/models.py:186 msgid "Parts are salable by default" msgstr "" -#: common/models.py:185 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:316 +#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 msgid "Trackable" msgstr "" -#: common/models.py:186 +#: common/models.py:193 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:192 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:28 msgid "Virtual" msgstr "" -#: common/models.py:193 +#: common/models.py:200 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:199 +#: common/models.py:206 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:200 +#: common/models.py:207 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:206 +#: common/models.py:213 msgid "Debug Mode" msgstr "" -#: common/models.py:207 +#: common/models.py:214 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:213 +#: common/models.py:220 msgid "Page Size" msgstr "" -#: common/models.py:214 +#: common/models.py:221 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:224 +#: common/models.py:231 msgid "Test Reports" msgstr "" -#: common/models.py:225 +#: common/models.py:232 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:231 +#: common/models.py:238 msgid "Stock Expiry" msgstr "" -#: common/models.py:232 +#: common/models.py:239 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:238 +#: common/models.py:245 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:239 +#: common/models.py:246 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:245 +#: common/models.py:252 msgid "Stock Stale Time" msgstr "" -#: common/models.py:246 +#: common/models.py:253 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:248 part/templates/part/detail.html:121 +#: common/models.py:255 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:253 +#: common/models.py:260 msgid "Build Expired Stock" msgstr "" -#: common/models.py:254 +#: common/models.py:261 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:260 +#: common/models.py:267 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:261 +#: common/models.py:268 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:267 +#: common/models.py:274 msgid "Group by Part" msgstr "" -#: common/models.py:268 +#: common/models.py:275 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:274 +#: common/models.py:281 msgid "Recent Stock Count" msgstr "" -#: common/models.py:275 +#: common/models.py:282 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:281 +#: common/models.py:288 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:282 +#: common/models.py:289 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:287 +#: common/models.py:294 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:288 +#: common/models.py:295 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:292 +#: common/models.py:299 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:293 +#: common/models.py:300 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:298 +#: common/models.py:305 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:299 +#: common/models.py:306 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:522 +#: common/models.py:529 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:524 +#: common/models.py:531 msgid "Settings value" msgstr "" -#: common/models.py:559 +#: common/models.py:566 msgid "Must be an integer value" msgstr "" -#: common/models.py:582 +#: common/models.py:589 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:593 +#: common/models.py:600 msgid "Value must be an integer value" msgstr "" -#: common/models.py:616 +#: common/models.py:623 msgid "Key string must be unique" msgstr "" -#: common/models.py:697 company/forms.py:132 +#: common/models.py:704 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:705 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:706 +#: common/models.py:713 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:729 +#: common/models.py:736 msgid "Default" msgstr "" @@ -1656,224 +1739,253 @@ msgstr "" msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:37 company/models.py:143 -#: company/templates/company/detail.html:40 +#: company/forms.py:38 company/models.py:145 +#: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: company/forms.py:39 company/models.py:147 msgid "Default currency used for this company" msgstr "" -#: company/forms.py:76 part/forms.py:46 +#: company/forms.py:77 part/forms.py:46 msgid "URL" msgstr "" -#: company/forms.py:77 part/forms.py:47 +#: company/forms.py:78 part/forms.py:47 msgid "Image URL" msgstr "" -#: company/forms.py:99 +#: company/forms.py:118 msgid "Single Price" msgstr "" -#: company/forms.py:101 +#: company/forms.py:120 msgid "Single quantity price" msgstr "" -#: company/models.py:100 -msgid "Company description" -msgstr "" - -#: company/models.py:101 -msgid "Description of the company" -msgstr "" - -#: company/models.py:105 company/templates/company/company_base.html:70 -#: company/templates/company/detail.html:31 templates/js/company.js:60 -msgid "Website" -msgstr "" - -#: company/models.py:105 -msgid "Company website URL" -msgstr "" - -#: company/models.py:108 company/templates/company/company_base.html:77 -msgid "Address" -msgstr "" - -#: company/models.py:109 -msgid "Company address" -msgstr "" - -#: company/models.py:112 -msgid "Phone number" -msgstr "" - -#: company/models.py:113 -msgid "Contact phone number" -msgstr "" - -#: company/models.py:116 company/templates/company/company_base.html:91 -msgid "Email" -msgstr "" - -#: company/models.py:116 -msgid "Contact email address" -msgstr "" - -#: company/models.py:119 company/templates/company/company_base.html:98 -msgid "Contact" -msgstr "" - -#: company/models.py:120 -msgid "Point of contact" -msgstr "" - -#: company/models.py:122 company/models.py:359 order/models.py:103 -#: part/models.py:743 -#: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1557 templates/js/company.js:208 templates/js/part.js:430 -msgid "Link" -msgstr "" - -#: company/models.py:122 -msgid "Link to external company information" -msgstr "" - -#: company/models.py:130 part/models.py:753 -msgid "Image" -msgstr "" - -#: company/models.py:135 -msgid "is customer" -msgstr "" - -#: company/models.py:135 -msgid "Do you sell items to this company?" -msgstr "" - -#: company/models.py:137 -msgid "is supplier" -msgstr "" - -#: company/models.py:137 -msgid "Do you purchase items from this company?" -msgstr "" - -#: company/models.py:139 -msgid "is manufacturer" -msgstr "" - -#: company/models.py:139 -msgid "Does this company manufacture parts?" -msgstr "" - -#: company/models.py:319 stock/models.py:371 -#: stock/templates/stock/item_base.html:220 -msgid "Base Part" -msgstr "" - -#: company/models.py:323 order/views.py:1372 -msgid "Select part" -msgstr "" - -#: company/models.py:329 company/templates/company/detail.html:60 -#: company/templates/company/supplier_part_base.html:83 -#: company/templates/company/supplier_part_detail.html:25 order/models.py:190 -#: order/templates/order/order_base.html:92 -#: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:170 -#: stock/templates/stock/item_base.html:337 templates/js/company.js:48 -#: templates/js/company.js:164 templates/js/order.js:170 -msgid "Supplier" -msgstr "" - -#: company/models.py:330 -msgid "Select supplier" -msgstr "" - -#: company/models.py:335 company/templates/company/supplier_part_base.html:87 -#: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:171 -msgid "SKU" -msgstr "" - -#: company/models.py:336 -msgid "Supplier stock keeping unit" -msgstr "" - -#: company/models.py:346 company/templates/company/detail.html:55 -#: company/templates/company/supplier_part_base.html:93 -#: company/templates/company/supplier_part_detail.html:34 part/bom.py:172 -#: templates/js/company.js:44 templates/js/company.js:188 -msgid "Manufacturer" -msgstr "" - -#: company/models.py:347 +#: company/forms.py:128 company/models.py:324 msgid "Select manufacturer" msgstr "" -#: company/models.py:353 company/templates/company/supplier_part_base.html:99 +#: company/forms.py:134 company/models.py:331 +msgid "Manufacturer Part Number" +msgstr "" + +#: company/forms.py:136 company/models.py:330 +#: company/templates/company/manufacturer_part_base.html:89 +#: company/templates/company/manufacturer_part_detail.html:26 +#: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:173 -#: templates/js/company.js:204 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 +#: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:354 -msgid "Manufacturer part number" +#: company/models.py:102 +msgid "Company description" msgstr "" -#: company/models.py:360 +#: company/models.py:103 +msgid "Description of the company" +msgstr "" + +#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/templates/company/detail.html:33 templates/js/company.js:60 +msgid "Website" +msgstr "" + +#: company/models.py:107 +msgid "Company website URL" +msgstr "" + +#: company/models.py:110 company/templates/company/company_base.html:77 +msgid "Address" +msgstr "" + +#: company/models.py:111 +msgid "Company address" +msgstr "" + +#: company/models.py:114 +msgid "Phone number" +msgstr "" + +#: company/models.py:115 +msgid "Contact phone number" +msgstr "" + +#: company/models.py:118 company/templates/company/company_base.html:91 +msgid "Email" +msgstr "" + +#: company/models.py:118 +msgid "Contact email address" +msgstr "" + +#: company/models.py:121 company/templates/company/company_base.html:98 +msgid "Contact" +msgstr "" + +#: company/models.py:122 +msgid "Point of contact" +msgstr "" + +#: company/models.py:124 company/models.py:336 company/models.py:488 +#: order/models.py:103 part/models.py:743 +#: report/templates/report/inventree_build_order_base.html:165 +#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/part.js:431 +msgid "Link" +msgstr "" + +#: company/models.py:124 +msgid "Link to external company information" +msgstr "" + +#: company/models.py:132 part/models.py:753 +msgid "Image" +msgstr "" + +#: company/models.py:137 +msgid "is customer" +msgstr "" + +#: company/models.py:137 +msgid "Do you sell items to this company?" +msgstr "" + +#: company/models.py:139 +msgid "is supplier" +msgstr "" + +#: company/models.py:139 +msgid "Do you purchase items from this company?" +msgstr "" + +#: company/models.py:141 +msgid "is manufacturer" +msgstr "" + +#: company/models.py:141 +msgid "Does this company manufacture parts?" +msgstr "" + +#: company/models.py:308 company/models.py:459 stock/models.py:373 +#: stock/templates/stock/item_base.html:224 +msgid "Base Part" +msgstr "" + +#: company/models.py:312 company/models.py:463 order/views.py:1384 +msgid "Select part" +msgstr "" + +#: company/models.py:323 company/templates/company/detail.html:57 +#: company/templates/company/manufacturer_part_base.html:85 +#: company/templates/company/manufacturer_part_detail.html:25 +#: company/templates/company/supplier_part_base.html:94 +#: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 +#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: templates/js/company.js:44 templates/js/company.js:165 +#: templates/js/company.js:289 +msgid "Manufacturer" +msgstr "" + +#: company/models.py:337 +msgid "URL for external manufacturer part link" +msgstr "" + +#: company/models.py:343 +msgid "Manufacturer part description" +msgstr "" + +#: company/models.py:469 company/templates/company/detail.html:62 +#: company/templates/company/supplier_part_base.html:84 +#: company/templates/company/supplier_part_detail.html:25 order/models.py:190 +#: order/templates/order/order_base.html:92 +#: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 +#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: templates/js/company.js:48 templates/js/company.js:263 +#: templates/js/order.js:170 +msgid "Supplier" +msgstr "" + +#: company/models.py:470 +msgid "Select supplier" +msgstr "" + +#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/templates/company/supplier_part_detail.html:26 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 +#: part/bom.py:287 +msgid "SKU" +msgstr "" + +#: company/models.py:476 +msgid "Supplier stock keeping unit" +msgstr "" + +#: company/models.py:482 +#: company/templates/company/manufacturer_part_base.html:6 +#: company/templates/company/manufacturer_part_base.html:19 +#: stock/templates/stock/item_base.html:346 +msgid "Manufacturer Part" +msgstr "" + +#: company/models.py:483 +msgid "Select manufacturer part" +msgstr "" + +#: company/models.py:489 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:366 +#: company/models.py:495 msgid "Supplier part description" msgstr "" -#: company/models.py:371 company/templates/company/supplier_part_base.html:113 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2170 +#: company/models.py:500 company/templates/company/supplier_part_base.html:115 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:375 +#: company/models.py:504 msgid "base cost" msgstr "" -#: company/models.py:375 +#: company/models.py:504 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:377 company/templates/company/supplier_part_base.html:106 -#: stock/models.py:395 stock/templates/stock/item_base.html:295 +#: company/models.py:506 company/templates/company/supplier_part_base.html:108 +#: stock/models.py:397 stock/templates/stock/item_base.html:299 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:377 +#: company/models.py:506 msgid "Part packaging" msgstr "" -#: company/models.py:379 +#: company/models.py:508 msgid "multiple" msgstr "" -#: company/models.py:379 +#: company/models.py:508 msgid "Order multiple" msgstr "" #: company/templates/company/assigned_stock.html:10 -#: company/templates/company/navbar.html:51 -#: company/templates/company/navbar.html:54 templates/js/build.js:411 +#: company/templates/company/navbar.html:62 +#: company/templates/company/navbar.html:65 templates/js/build.js:467 msgid "Assigned Stock" msgstr "" #: company/templates/company/company_base.html:9 #: company/templates/company/company_base.html:35 -#: templates/InvenTree/search.html:288 templates/js/company.js:33 +#: templates/InvenTree/search.html:304 templates/js/company.js:33 msgid "Company" msgstr "" @@ -1895,7 +2007,7 @@ msgstr "" msgid "Edit company information" msgstr "" -#: company/templates/company/company_base.html:56 company/views.py:324 +#: company/templates/company/company_base.html:56 company/views.py:326 msgid "Delete Company" msgstr "" @@ -1918,91 +2030,87 @@ msgstr "" #, python-format msgid "" "There are %(count)s parts sourced from this company.
\n" -"If this supplier is deleted, these supplier part entries will also be " -"deleted." +"If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" #: company/templates/company/detail.html:21 msgid "Company Name" msgstr "" -#: company/templates/company/detail.html:34 +#: company/templates/company/detail.html:36 msgid "No website specified" msgstr "" -#: company/templates/company/detail.html:43 +#: company/templates/company/detail.html:45 msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:65 order/models.py:440 -#: order/templates/order/sales_order_base.html:92 stock/models.py:413 -#: stock/models.py:414 stock/templates/stock/item_base.html:247 +#: company/templates/company/detail.html:67 order/models.py:450 +#: order/templates/order/sales_order_base.html:92 stock/models.py:415 +#: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 msgid "Customer" msgstr "" -#: company/templates/company/detail_part.html:10 -#: templates/InvenTree/search.html:148 -msgid "Supplier Parts" +#: company/templates/company/detail_manufacturer_part.html:11 +#: templates/InvenTree/search.html:149 +msgid "Manufacturer Parts" msgstr "" -#: company/templates/company/detail_part.html:20 -#: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 -msgid "Create new supplier part" +#: company/templates/company/detail_manufacturer_part.html:22 +msgid "Create new manufacturer part" msgstr "" -#: company/templates/company/detail_part.html:21 -#: order/templates/order/purchase_order_detail.html:74 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1086 -msgid "New Supplier Part" +#: company/templates/company/detail_manufacturer_part.html:23 +#: part/templates/part/manufacturer.html:19 +msgid "New Manufacturer Part" msgstr "" -#: company/templates/company/detail_part.html:26 -#: part/templates/part/category.html:122 part/templates/part/supplier.html:20 +#: company/templates/company/detail_manufacturer_part.html:28 +#: company/templates/company/detail_supplier_part.html:27 +#: company/templates/company/manufacturer_part_suppliers.html:20 +#: part/templates/part/category.html:122 +#: part/templates/part/manufacturer.html:22 +#: part/templates/part/supplier.html:20 msgid "Options" msgstr "" -#: company/templates/company/detail_part.html:31 +#: company/templates/company/detail_manufacturer_part.html:33 +#: company/templates/company/detail_supplier_part.html:32 #: part/templates/part/category.html:127 msgid "Order parts" msgstr "" -#: company/templates/company/detail_part.html:34 +#: company/templates/company/detail_manufacturer_part.html:36 +#: company/templates/company/detail_supplier_part.html:35 msgid "Delete parts" msgstr "" -#: company/templates/company/detail_part.html:34 +#: company/templates/company/detail_manufacturer_part.html:36 +#: company/templates/company/detail_supplier_part.html:35 msgid "Delete Parts" msgstr "" -#: company/templates/company/detail_part.html:66 +#: company/templates/company/detail_manufacturer_part.html:66 +#: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1080 +#: templates/js/stock.js:1157 msgid "New Part" msgstr "" -#: company/templates/company/detail_part.html:67 +#: company/templates/company/detail_manufacturer_part.html:67 +#: company/templates/company/detail_supplier_part.html:67 msgid "Create new Part" msgstr "" -#: company/templates/company/detail_part.html:72 company/views.py:62 -#: order/templates/order/purchase_orders.html:183 -#: part/templates/part/supplier.html:50 -msgid "New Supplier" -msgstr "" - -#: company/templates/company/detail_part.html:73 company/views.py:279 -#: order/templates/order/purchase_orders.html:184 -msgid "Create new Supplier" -msgstr "" - -#: company/templates/company/detail_part.html:78 company/views.py:69 +#: company/templates/company/detail_manufacturer_part.html:72 +#: company/views.py:71 part/templates/part/manufacturer.html:52 #: part/templates/part/supplier.html:56 msgid "New Manufacturer" msgstr "" -#: company/templates/company/detail_part.html:79 company/views.py:282 +#: company/templates/company/detail_manufacturer_part.html:73 +#: company/views.py:284 msgid "Create new Manufacturer" msgstr "" @@ -2017,68 +2125,172 @@ msgstr "" msgid "Export" msgstr "" -#: company/templates/company/index.html:7 +#: company/templates/company/detail_supplier_part.html:11 +#: company/templates/company/manufacturer_part_navbar.html:11 +#: company/templates/company/manufacturer_part_suppliers.html:10 +#: templates/InvenTree/search.html:164 +msgid "Supplier Parts" +msgstr "" + +#: company/templates/company/detail_supplier_part.html:21 +#: order/templates/order/order_wizard/select_parts.html:42 +#: order/templates/order/purchase_order_detail.html:50 +msgid "Create new supplier part" +msgstr "" + +#: company/templates/company/detail_supplier_part.html:22 +#: company/templates/company/manufacturer_part_suppliers.html:17 +#: order/templates/order/purchase_order_detail.html:49 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +msgid "New Supplier Part" +msgstr "" + +#: company/templates/company/detail_supplier_part.html:72 +#: company/templates/company/manufacturer_part_suppliers.html:47 +#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: part/templates/part/supplier.html:50 +msgid "New Supplier" +msgstr "" + +#: company/templates/company/detail_supplier_part.html:73 company/views.py:281 +#: order/templates/order/purchase_orders.html:184 +msgid "Create new Supplier" +msgstr "" + +#: company/templates/company/index.html:8 msgid "Supplier List" msgstr "" -#: company/templates/company/navbar.html:20 -msgid "Supplied Parts" +#: company/templates/company/manufacturer_part_base.html:36 +#: company/templates/company/supplier_part_base.html:36 +#: company/templates/company/supplier_part_orders.html:17 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +msgid "Order part" msgstr "" -#: company/templates/company/navbar.html:23 -#: order/templates/order/receive_parts.html:14 part/models.py:322 -#: part/templates/part/cat_link.html:7 part/templates/part/category.html:95 -#: part/templates/part/category_navbar.html:11 -#: part/templates/part/category_navbar.html:14 -#: part/templates/part/category_partlist.html:10 -#: templates/InvenTree/index.html:96 templates/InvenTree/search.html:113 -#: templates/InvenTree/settings/tabs.html:25 templates/navbar.html:23 -#: templates/stats.html:59 templates/stats.html:68 users/models.py:38 -msgid "Parts" +#: company/templates/company/manufacturer_part_base.html:41 +msgid "Edit manufacturer part" msgstr "" -#: company/templates/company/navbar.html:27 part/templates/part/navbar.html:33 -#: stock/templates/stock/location.html:100 -#: stock/templates/stock/location.html:115 templates/InvenTree/search.html:182 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 -msgid "Stock Items" +#: company/templates/company/manufacturer_part_base.html:45 +msgid "Delete manufacturer part" msgstr "" -#: company/templates/company/navbar.html:30 -#: company/templates/company/part_navbar.html:14 -#: part/templates/part/navbar.html:36 stock/templates/stock/loc_link.html:7 -#: stock/templates/stock/location.html:29 -#: stock/templates/stock/stock_app_base.html:9 -#: templates/InvenTree/index.html:127 templates/InvenTree/search.html:180 -#: templates/InvenTree/search.html:216 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:172 -#: templates/js/part.js:397 templates/js/stock.js:563 templates/navbar.html:26 +#: company/templates/company/manufacturer_part_base.html:57 +#: company/templates/company/manufacturer_part_detail.html:10 +msgid "Manufacturer Part Details" +msgstr "" + +#: company/templates/company/manufacturer_part_base.html:62 +#: company/templates/company/manufacturer_part_detail.html:18 +#: company/templates/company/supplier_part_base.html:61 +#: company/templates/company/supplier_part_detail.html:18 +msgid "Internal Part" +msgstr "" + +#: company/templates/company/manufacturer_part_delete.html:6 +msgid "Are you sure you want to delete the following Manufacturer Parts?" +msgstr "" + +#: company/templates/company/manufacturer_part_delete.html:36 +#, python-format +msgid "There are %(count)s suppliers defined for this manufacturer part. If you delete it, the following supplier parts will also be deleted:" +msgstr "" + +#: company/templates/company/manufacturer_part_navbar.html:14 +#: company/views.py:63 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: templates/navbar.html:35 +msgid "Suppliers" +msgstr "" + +#: company/templates/company/manufacturer_part_navbar.html:19 +msgid "Manufacturer Part Stock" +msgstr "" + +#: company/templates/company/manufacturer_part_navbar.html:22 +#: company/templates/company/navbar.html:41 +#: company/templates/company/supplier_part_navbar.html:15 +#: part/templates/part/navbar.html:36 stock/api.py:51 +#: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 +#: stock/templates/stock/stock_app_base.html:10 +#: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 +#: templates/InvenTree/search.html:232 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" -#: company/templates/company/navbar.html:36 -#: company/templates/company/navbar.html:45 -#: company/templates/company/navbar.html:48 +#: company/templates/company/manufacturer_part_navbar.html:26 +msgid "Manufacturer Part Orders" +msgstr "" + +#: company/templates/company/manufacturer_part_navbar.html:29 +#: company/templates/company/supplier_part_navbar.html:22 +msgid "Orders" +msgstr "" + +#: company/templates/company/manufacturer_part_suppliers.html:22 +#: part/templates/part/supplier.html:22 +msgid "Delete supplier parts" +msgstr "" + +#: company/templates/company/manufacturer_part_suppliers.html:22 +#: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 +#: part/templates/part/related.html:44 part/templates/part/supplier.html:22 +#: stock/views.py:1002 users/models.py:187 +msgid "Delete" +msgstr "" + +#: company/templates/company/manufacturer_part_suppliers.html:48 +#: part/templates/part/supplier.html:51 +msgid "Create new supplier" +msgstr "" + +#: company/templates/company/navbar.html:20 +#: company/templates/company/navbar.html:23 +msgid "Manufactured Parts" +msgstr "" + +#: company/templates/company/navbar.html:29 +#: company/templates/company/navbar.html:32 +msgid "Supplied Parts" +msgstr "" + +#: company/templates/company/navbar.html:38 part/templates/part/navbar.html:33 +#: stock/templates/stock/location.html:107 +#: stock/templates/stock/location.html:122 +#: stock/templates/stock/location.html:136 +#: stock/templates/stock/location_navbar.html:22 +#: stock/templates/stock/location_navbar.html:29 +#: templates/InvenTree/search.html:198 templates/js/stock.js:968 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +msgid "Stock Items" +msgstr "" + +#: company/templates/company/navbar.html:47 +#: company/templates/company/navbar.html:56 +#: company/templates/company/navbar.html:59 #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:92 part/templates/part/navbar.html:95 -#: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:227 -#: templates/InvenTree/search.html:330 +#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 +#: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" -#: company/templates/company/navbar.html:39 +#: company/templates/company/navbar.html:50 #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:78 part/templates/part/navbar.html:81 -#: part/templates/part/orders.html:10 templates/InvenTree/index.html:204 -#: templates/InvenTree/search.html:300 +#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 +#: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2086,32 +2298,6 @@ msgstr "" msgid "Company Notes" msgstr "" -#: company/templates/company/part_navbar.html:11 -#: company/templates/company/supplier_part_stock.html:10 -msgid "Supplier Part Stock" -msgstr "" - -#: company/templates/company/part_navbar.html:18 -#: company/templates/company/supplier_part_orders.html:10 -msgid "Supplier Part Orders" -msgstr "" - -#: company/templates/company/part_navbar.html:21 -msgid "Orders" -msgstr "" - -#: company/templates/company/part_navbar.html:25 -msgid "Supplier Part Pricing" -msgstr "" - -#: company/templates/company/part_navbar.html:28 -msgid "Pricing" -msgstr "" - -#: company/templates/company/partdelete.html:5 -msgid "Are you sure you want to delete the following Supplier Parts?" -msgstr "" - #: company/templates/company/purchase_orders.html:18 #: order/templates/order/purchase_orders.html:20 msgid "Create new purchase order" @@ -2132,34 +2318,45 @@ msgstr "" msgid "New Sales Order" msgstr "" -#: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:380 -#: stock/templates/stock/item_base.html:342 templates/js/company.js:180 +#: company/templates/company/supplier_part_base.html:7 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 +#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 msgid "Supplier Part" msgstr "" -#: company/templates/company/supplier_part_base.html:35 -#: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:64 -msgid "Order part" -msgstr "" - -#: company/templates/company/supplier_part_base.html:39 +#: company/templates/company/supplier_part_base.html:40 msgid "Edit supplier part" msgstr "" -#: company/templates/company/supplier_part_base.html:43 +#: company/templates/company/supplier_part_base.html:44 msgid "Delete supplier part" msgstr "" -#: company/templates/company/supplier_part_base.html:55 +#: company/templates/company/supplier_part_base.html:56 #: company/templates/company/supplier_part_detail.html:10 msgid "Supplier Part Details" msgstr "" -#: company/templates/company/supplier_part_base.html:60 -#: company/templates/company/supplier_part_detail.html:18 -msgid "Internal Part" +#: company/templates/company/supplier_part_delete.html:5 +msgid "Are you sure you want to delete the following Supplier Parts?" +msgstr "" + +#: company/templates/company/supplier_part_navbar.html:12 +#: company/templates/company/supplier_part_stock.html:10 +msgid "Supplier Part Stock" +msgstr "" + +#: company/templates/company/supplier_part_navbar.html:19 +#: company/templates/company/supplier_part_orders.html:10 +msgid "Supplier Part Orders" +msgstr "" + +#: company/templates/company/supplier_part_navbar.html:26 +msgid "Supplier Part Pricing" +msgstr "" + +#: company/templates/company/supplier_part_navbar.html:29 +msgid "Pricing" msgstr "" #: company/templates/company/supplier_part_orders.html:18 @@ -2171,8 +2368,8 @@ msgstr "" msgid "Pricing Information" msgstr "" -#: company/templates/company/supplier_part_pricing.html:19 company/views.py:569 -#: part/templates/part/sale_prices.html:17 part/views.py:2618 +#: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2191,99 +2388,106 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:61 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:291 -#: templates/navbar.html:35 -msgid "Suppliers" -msgstr "" - -#: company/views.py:68 templates/InvenTree/search.html:308 +#: company/views.py:70 part/templates/part/navbar.html:72 +#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" -#: company/views.py:75 templates/InvenTree/search.html:321 +#: company/views.py:77 templates/InvenTree/search.html:336 #: templates/navbar.html:45 msgid "Customers" msgstr "" -#: company/views.py:76 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:185 msgid "New Customer" msgstr "" -#: company/views.py:84 +#: company/views.py:86 msgid "Companies" msgstr "" -#: company/views.py:85 +#: company/views.py:87 msgid "New Company" msgstr "" -#: company/views.py:167 part/views.py:848 +#: company/views.py:169 part/views.py:848 msgid "Download Image" msgstr "" -#: company/views.py:196 part/views.py:880 +#: company/views.py:198 part/views.py:880 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:212 part/views.py:896 +#: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" -#: company/views.py:241 +#: company/views.py:243 msgid "Update Company Image" msgstr "" -#: company/views.py:247 +#: company/views.py:249 msgid "Updated company image" msgstr "" -#: company/views.py:257 +#: company/views.py:259 msgid "Edit Company" msgstr "" -#: company/views.py:262 +#: company/views.py:264 msgid "Edited company information" msgstr "" -#: company/views.py:285 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:186 msgid "Create new Customer" msgstr "" -#: company/views.py:287 +#: company/views.py:289 msgid "Create new Company" msgstr "" -#: company/views.py:314 +#: company/views.py:316 msgid "Created new company" msgstr "" -#: company/views.py:330 +#: company/views.py:332 msgid "Company was deleted" msgstr "" -#: company/views.py:355 +#: company/views.py:357 +msgid "Edit Manufacturer Part" +msgstr "" + +#: company/views.py:366 +msgid "Create New Manufacturer Part" +msgstr "" + +#: company/views.py:440 +msgid "Delete Manufacturer Part" +msgstr "" + +#: company/views.py:528 msgid "Edit Supplier Part" msgstr "" -#: company/views.py:378 templates/js/stock.js:1087 +#: company/views.py:578 templates/js/stock.js:1164 msgid "Create new Supplier Part" msgstr "" -#: company/views.py:497 +#: company/views.py:722 msgid "Delete Supplier Part" msgstr "" -#: company/views.py:574 part/views.py:2622 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:630 part/views.py:2666 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:645 part/views.py:2680 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2331,11 +2535,11 @@ msgstr "" msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:273 +#: label/models.py:222 label/models.py:275 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:274 report/models.py:294 +#: label/models.py:223 label/models.py:276 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2373,9 +2577,8 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 -msgid "" -"Target date for order completion. Order will be overdue after this date." +#: order/forms.py:145 order/models.py:462 +msgid "Target date for order completion. Order will be overdue after this date." msgstr "" #: order/forms.py:235 @@ -2410,7 +2613,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2444,16 +2647,15 @@ msgid "Target Delivery Date" msgstr "" #: order/models.py:213 -msgid "" -"Expected date for order delivery. Order will be overdue after this date." +msgid "Expected date for order delivery. Order will be overdue after this date." msgstr "" #: order/models.py:219 msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:950 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2461,120 +2663,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:309 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:207 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:506 -#: stock/templates/stock/item_base.html:316 +#: order/models.py:658 stock/models.py:508 +#: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2622,18 +2832,38 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 msgid "Mark this order as complete?" msgstr "" -#: order/templates/order/order_issue.html:7 -msgid "" -"After placing this purchase order, line items will no longer be editable." +#: order/templates/order/order_complete.html:10 +msgid "This order has line items which have not been marked as received." +msgstr "" + +#: order/templates/order/order_complete.html:11 +msgid "Completing this order means that the order and line items will no longer be editable." +msgstr "" + +#: order/templates/order/order_issue.html:8 +msgid "After placing this purchase order, line items will no longer be editable." msgstr "" #: order/templates/order/order_notes.html:13 @@ -2657,7 +2887,8 @@ msgid "Select Supplier" msgstr "" #: order/templates/order/order_wizard/select_parts.html:57 -msgid "Select a supplier for" +#, python-format +msgid "Select a supplier for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_parts.html:69 @@ -2683,11 +2914,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2709,43 +2942,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:197 part/templates/part/category.html:239 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1092 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:35 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:198 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:239 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:240 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:245 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2755,7 +2974,21 @@ msgid "Print Order Reports" msgstr "" #: order/templates/order/receive_parts.html:8 -msgid "Receive outstanding parts for" +#, python-format +msgid "Receive outstanding parts for %(order)s - %(desc)s" +msgstr "" + +#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: part/models.py:322 part/templates/part/cat_link.html:7 +#: part/templates/part/category.html:99 +#: part/templates/part/category_navbar.html:22 +#: part/templates/part/category_navbar.html:29 +#: part/templates/part/category_partlist.html:10 +#: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 +#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: users/models.py:40 +msgid "Parts" msgstr "" #: order/templates/order/receive_parts.html:15 @@ -2767,7 +3000,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:128 templates/js/part.js:413 +#: part/templates/part/part_base.html:129 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -2807,30 +3040,26 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 -#: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:418 stock/templates/stock/item_base.html:234 -#: templates/js/build.js:418 -msgid "Serial Number" -msgstr "" - -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:338 -#: templates/js/build.js:571 templates/js/build.js:984 +#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:459 -#: templates/js/build.js:789 +#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:461 -#: templates/js/build.js:790 +#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" @@ -2842,8 +3071,8 @@ msgstr "" msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:523 -#: templates/js/build.js:785 +#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: templates/js/build.js:845 msgid "Allocated" msgstr "" @@ -2855,7 +3084,7 @@ msgstr "" msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:585 +#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 msgid "Allocate stock" msgstr "" @@ -2863,8 +3092,8 @@ msgstr "" msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:578 -#: templates/js/build.js:992 +#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: templates/js/build.js:1052 msgid "Build stock" msgstr "" @@ -2877,9 +3106,7 @@ msgid "Sales Order Notes" msgstr "" #: order/templates/order/sales_order_ship.html:10 -msgid "" -"This order has not been fully allocated. If the order is marked as shipped, " -"it can no longer be adjusted." +msgid "This order has not been fully allocated. If the order is marked as shipped, it can no longer be adjusted." msgstr "" #: order/templates/order/sales_order_ship.html:12 @@ -3011,87 +3238,87 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" #: part/bom.py:138 part/models.py:72 part/models.py:762 -#: part/templates/part/category.html:62 part/templates/part/detail.html:90 +#: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:116 +#: part/bom.py:139 part/templates/part/part_base.html:117 msgid "Available Stock" msgstr "" -#: part/bom.py:278 +#: part/bom.py:379 #, python-brace-format msgid "Unsupported file format: {f}" msgstr "" -#: part/bom.py:283 +#: part/bom.py:384 msgid "Error reading BOM file (invalid data)" msgstr "" -#: part/bom.py:285 +#: part/bom.py:386 msgid "Error reading BOM file (incorrect row size)" msgstr "" @@ -3136,94 +3363,102 @@ msgid "Include part stock data in exported BOM" msgstr "" #: part/forms.py:99 -msgid "Include Supplier Data" +msgid "Include Manufacturer Data" msgstr "" #: part/forms.py:99 +msgid "Include part manufacturer data in exported BOM" +msgstr "" + +#: part/forms.py:101 +msgid "Include Supplier Data" +msgstr "" + +#: part/forms.py:101 msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:120 part/models.py:2057 +#: part/forms.py:122 part/models.py:2077 msgid "Parent Part" msgstr "" -#: part/forms.py:121 part/templates/part/bom_duplicate.html:7 +#: part/forms.py:123 part/templates/part/bom_duplicate.html:7 msgid "Select parent part to copy BOM from" msgstr "" -#: part/forms.py:127 +#: part/forms.py:129 msgid "Clear existing BOM items" msgstr "" -#: part/forms.py:133 +#: part/forms.py:135 msgid "Confirm BOM duplication" msgstr "" -#: part/forms.py:151 +#: part/forms.py:153 msgid "validate" msgstr "" -#: part/forms.py:151 +#: part/forms.py:153 msgid "Confirm that the BOM is correct" msgstr "" -#: part/forms.py:163 +#: part/forms.py:165 msgid "BOM file" msgstr "" -#: part/forms.py:163 +#: part/forms.py:165 msgid "Select BOM file to upload" msgstr "" -#: part/forms.py:182 +#: part/forms.py:184 msgid "Related Part" msgstr "" -#: part/forms.py:201 +#: part/forms.py:203 msgid "Select part category" msgstr "" -#: part/forms.py:218 +#: part/forms.py:220 msgid "Duplicate all BOM data for this part" msgstr "" -#: part/forms.py:219 +#: part/forms.py:221 msgid "Copy BOM" msgstr "" -#: part/forms.py:224 +#: part/forms.py:226 msgid "Duplicate all parameter data for this part" msgstr "" -#: part/forms.py:225 +#: part/forms.py:227 msgid "Copy Parameters" msgstr "" -#: part/forms.py:230 +#: part/forms.py:232 msgid "Confirm part creation" msgstr "" -#: part/forms.py:235 +#: part/forms.py:237 msgid "Include category parameter templates" msgstr "" -#: part/forms.py:240 +#: part/forms.py:242 msgid "Include parent categories parameter templates" msgstr "" -#: part/forms.py:320 +#: part/forms.py:322 msgid "Add parameter template to same level categories" msgstr "" -#: part/forms.py:324 +#: part/forms.py:326 msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:342 part/models.py:2151 +#: part/forms.py:344 part/models.py:2171 msgid "Sub part" msgstr "" -#: part/forms.py:370 +#: part/forms.py:372 msgid "Input quantity for price calculation" msgstr "" @@ -3239,15 +3474,15 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2103 -#: part/templates/part/part_app_base.html:9 +#: part/models.py:82 part/models.py:2123 +#: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" -#: part/models.py:83 part/templates/part/category.html:19 -#: part/templates/part/category.html:90 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:126 templates/stats.html:63 -#: users/models.py:37 +#: part/models.py:83 part/templates/part/category.html:23 +#: part/templates/part/category.html:94 part/templates/part/category.html:141 +#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3300,7 +3535,7 @@ msgstr "" msgid "Part description" msgstr "" -#: part/models.py:716 part/templates/part/category.html:69 +#: part/models.py:716 part/templates/part/category.html:73 #: part/templates/part/detail.html:67 msgid "Keywords" msgstr "" @@ -3309,8 +3544,8 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2102 part/templates/part/detail.html:73 -#: part/templates/part/set_category.html:15 templates/js/part.js:384 +#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3319,7 +3554,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:93 templates/js/part.js:160 +#: part/templates/part/part_base.html:94 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3332,7 +3567,7 @@ msgid "Part revision or version number" msgstr "" #: part/models.py:738 part/templates/part/detail.html:35 report/models.py:198 -#: templates/js/part.js:164 +#: templates/js/part.js:165 msgid "Revision" msgstr "" @@ -3364,7 +3599,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2031 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3395,7 +3630,7 @@ msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 #: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:214 templates/js/table_filters.js:283 +#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 msgid "Active" msgstr "" @@ -3431,170 +3666,168 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1929 +#: part/models.py:1949 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1946 +#: part/models.py:1966 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1966 templates/js/part.js:561 templates/js/stock.js:104 +#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:1967 +#: part/models.py:1987 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1972 +#: part/models.py:1992 msgid "Test Description" msgstr "" -#: part/models.py:1973 +#: part/models.py:1993 msgid "Enter description for this test" msgstr "" -#: part/models.py:1978 templates/js/part.js:570 -#: templates/js/table_filters.js:200 +#: part/models.py:1998 templates/js/part.js:647 +#: templates/js/table_filters.js:222 msgid "Required" msgstr "" -#: part/models.py:1979 +#: part/models.py:1999 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1984 templates/js/part.js:578 +#: part/models.py:2004 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:1985 +#: part/models.py:2005 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1990 templates/js/part.js:585 +#: part/models.py:2010 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:1991 +#: part/models.py:2011 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2024 +#: part/models.py:2044 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2029 +#: part/models.py:2049 msgid "Parameter Name" msgstr "" -#: part/models.py:2031 +#: part/models.py:2051 msgid "Parameter Units" msgstr "" -#: part/models.py:2059 part/models.py:2108 part/models.py:2109 +#: part/models.py:2079 part/models.py:2128 part/models.py:2129 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2061 +#: part/models.py:2081 msgid "Data" msgstr "" -#: part/models.py:2061 +#: part/models.py:2081 msgid "Parameter Value" msgstr "" -#: part/models.py:2113 templates/InvenTree/settings/category.html:67 +#: part/models.py:2133 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2114 +#: part/models.py:2134 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2143 +#: part/models.py:2163 msgid "Select parent part" msgstr "" -#: part/models.py:2152 +#: part/models.py:2172 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2158 +#: part/models.py:2178 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2160 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2160 +#: part/models.py:2180 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2163 +#: part/models.py:2183 msgid "Overage" msgstr "" -#: part/models.py:2164 +#: part/models.py:2184 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2167 +#: part/models.py:2187 msgid "BOM item reference" msgstr "" -#: part/models.py:2170 +#: part/models.py:2190 msgid "BOM item notes" msgstr "" -#: part/models.py:2172 +#: part/models.py:2192 msgid "Checksum" msgstr "" -#: part/models.py:2172 +#: part/models.py:2192 msgid "BOM line checksum" msgstr "" -#: part/models.py:2176 templates/js/bom.js:275 templates/js/bom.js:282 +#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 #: templates/js/table_filters.js:50 msgid "Inherited" msgstr "" -#: part/models.py:2177 +#: part/models.py:2197 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2253 part/views.py:1592 part/views.py:1644 +#: part/models.py:2273 part/views.py:1592 part/views.py:1644 #: stock/models.py:260 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2262 part/models.py:2264 +#: part/models.py:2282 part/models.py:2284 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2267 +#: part/models.py:2287 msgid "BOM Item" msgstr "" -#: part/models.py:2384 +#: part/models.py:2404 msgid "Part 1" msgstr "" -#: part/models.py:2388 +#: part/models.py:2408 msgid "Part 2" msgstr "" -#: part/models.py:2388 +#: part/models.py:2408 msgid "Select Related Part" msgstr "" -#: part/models.py:2420 -msgid "" -"Error creating relationship: check that the part is not related to itself " -"and that the relationship is unique" +#: part/models.py:2440 +msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" #: part/templates/part/allocation.html:11 @@ -3625,8 +3858,7 @@ msgstr "" #: part/templates/part/bom.html:21 #, python-format -msgid "" -"The BOM for %(part)s was last checked by %(checker)s on %(check_date)s" +msgid "The BOM for %(part)s was last checked by %(checker)s on %(check_date)s" msgstr "" #: part/templates/part/bom.html:25 @@ -3662,7 +3894,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1883 +#: part/templates/part/bom.html:61 part/views.py:1887 msgid "Export Bill of Materials" msgstr "" @@ -3679,7 +3911,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1081 +#: templates/js/stock.js:1158 msgid "Create New Part" msgstr "" @@ -3761,8 +3993,7 @@ msgid "Requirements for BOM upload" msgstr "" #: part/templates/part/bom_upload/upload_file.html:21 -msgid "" -"The BOM file must contain the required named columns as provided in the " +msgid "The BOM file must contain the required named columns as provided in the " msgstr "" #: part/templates/part/bom_upload/upload_file.html:21 @@ -3779,8 +4010,7 @@ msgstr "" #: part/templates/part/bom_validate.html:6 #, python-format -msgid "" -"Confirm that the Bill of Materials (BOM) is valid for:
%(part)s" +msgid "Confirm that the Bill of Materials (BOM) is valid for:
%(part)s" msgstr "" #: part/templates/part/bom_validate.html:9 @@ -3795,39 +4025,42 @@ msgstr "" msgid "Start New Build" msgstr "" -#: part/templates/part/category.html:20 +#: part/templates/part/category.html:24 msgid "All parts" msgstr "" -#: part/templates/part/category.html:25 part/views.py:2264 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" -#: part/templates/part/category.html:31 +#: part/templates/part/category.html:35 msgid "Edit part category" msgstr "" -#: part/templates/part/category.html:36 +#: part/templates/part/category.html:40 msgid "Delete part category" msgstr "" -#: part/templates/part/category.html:46 part/templates/part/category.html:85 +#: part/templates/part/category.html:50 part/templates/part/category.html:89 msgid "Category Details" msgstr "" -#: part/templates/part/category.html:51 +#: part/templates/part/category.html:55 msgid "Category Path" msgstr "" -#: part/templates/part/category.html:56 +#: part/templates/part/category.html:60 msgid "Category Description" msgstr "" -#: part/templates/part/category.html:75 +#: part/templates/part/category.html:79 +#: part/templates/part/category_navbar.html:11 +#: part/templates/part/category_navbar.html:18 +#: part/templates/part/subcategory.html:16 msgid "Subcategories" msgstr "" -#: part/templates/part/category.html:80 +#: part/templates/part/category.html:84 msgid "Parts (Including subcategories)" msgstr "" @@ -3847,24 +4080,24 @@ msgstr "" msgid "Export Data" msgstr "" -#: part/templates/part/category.html:198 +#: part/templates/part/category.html:186 #: stock/templates/stock/location.html:192 templates/js/stock.js:709 msgid "Create new location" msgstr "" -#: part/templates/part/category.html:203 part/templates/part/category.html:233 +#: part/templates/part/category.html:191 part/templates/part/category.html:221 msgid "New Category" msgstr "" -#: part/templates/part/category.html:204 +#: part/templates/part/category.html:192 msgid "Create new category" msgstr "" -#: part/templates/part/category.html:234 +#: part/templates/part/category.html:222 msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:240 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1359 msgid "Create new Stock Location" msgstr "" @@ -3873,17 +4106,12 @@ msgid "Are you sure you want to delete category" msgstr "" #: part/templates/part/category_delete.html:8 -#: part/templates/part/category_delete.html:25 -msgid "This category contains" -msgstr "" - -#: part/templates/part/category_delete.html:8 -msgid "child categories" +#, python-format +msgid "This category contains %(count)s child categories" msgstr "" #: part/templates/part/category_delete.html:9 -msgid "" -"If this category is deleted, these child categories will be moved to the" +msgid "If this category is deleted, these child categories will be moved to the" msgstr "" #: part/templates/part/category_delete.html:11 @@ -3895,22 +4123,21 @@ msgid "top level Parts category" msgstr "" #: part/templates/part/category_delete.html:25 -msgid "parts" +#, python-format +msgid "This category contains %(count)s parts" msgstr "" #: part/templates/part/category_delete.html:27 -msgid "" -"If this category is deleted, these parts will be moved to the parent category" +#, python-format +msgid "If this category is deleted, these parts will be moved to the parent category %(path)s" msgstr "" #: part/templates/part/category_delete.html:29 -msgid "" -"If this category is deleted, these parts will be moved to the top-level " -"category Teile" +msgid "If this category is deleted, these parts will be moved to the top-level category Teile" msgstr "" -#: part/templates/part/category_navbar.html:18 -#: part/templates/part/category_navbar.html:21 +#: part/templates/part/category_navbar.html:34 +#: part/templates/part/category_navbar.html:37 #: part/templates/part/navbar.html:22 msgid "Parameters" msgstr "" @@ -3925,7 +4152,8 @@ msgid "Duplicate Part" msgstr "" #: part/templates/part/copy_part.html:10 -msgid "Make a copy of part" +#, python-format +msgid "Make a copy of part '%(full_name)s'." msgstr "" #: part/templates/part/copy_part.html:14 @@ -3938,8 +4166,9 @@ msgstr "" msgid "The new part may be a duplicate of these existing parts" msgstr "" -#: part/templates/part/create_part.html:16 -msgid "match" +#: part/templates/part/create_part.html:17 +#, python-format +msgid "%(full_name)s - %(desc)s (%(match_per)s%% match)" msgstr "" #: part/templates/part/detail.html:11 part/templates/part/navbar.html:11 @@ -4022,6 +4251,19 @@ msgstr "" msgid "Part is not active" msgstr "" +#: part/templates/part/manufacturer.html:11 +msgid "Part Manufacturers" +msgstr "" + +#: part/templates/part/manufacturer.html:24 +msgid "Delete manufacturer parts" +msgstr "" + +#: part/templates/part/manufacturer.html:53 +#: part/templates/part/supplier.html:57 +msgid "Create new manufacturer" +msgstr "" + #: part/templates/part/navbar.html:26 part/templates/part/variants.html:11 msgid "Part Variants" msgstr "" @@ -4042,28 +4284,28 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:86 +#: part/templates/part/navbar.html:92 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:89 +#: part/templates/part/navbar.html:95 msgid "Sale Price" msgstr "" -#: part/templates/part/navbar.html:100 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:103 stock/templates/stock/item_base.html:382 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:107 part/templates/part/navbar.html:110 +#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:119 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" @@ -4079,7 +4321,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1652 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4088,11 +4330,6 @@ msgstr "" msgid "Edit" msgstr "" -#: part/templates/part/params.html:44 part/templates/part/related.html:44 -#: part/templates/part/supplier.html:22 stock/views.py:1002 users/models.py:182 -msgid "Delete" -msgstr "" - #: part/templates/part/params.html:68 msgid "New Template" msgstr "" @@ -4101,128 +4338,130 @@ msgstr "" msgid "Create New Parameter Template" msgstr "" -#: part/templates/part/part_app_base.html:11 +#: part/templates/part/part_app_base.html:12 msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:17 -msgid "This part is a variant of" +#: part/templates/part/part_base.html:18 +#, python-format +msgid "This part is a variant of %(link)s" msgstr "" -#: part/templates/part/part_base.html:32 templates/js/company.js:155 -#: templates/js/part.js:75 templates/js/part.js:152 +#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:39 +#: part/templates/part/part_base.html:40 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:46 -#: stock/templates/stock/item_base.html:127 -#: stock/templates/stock/location.html:44 +#: part/templates/part/part_base.html:47 +#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:48 -#: stock/templates/stock/item_base.html:129 -#: stock/templates/stock/location.html:46 templates/qr_button.html:1 +#: part/templates/part/part_base.html:49 +#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:145 -#: stock/templates/stock/location.html:47 +#: part/templates/part/part_base.html:50 +#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:54 +#: part/templates/part/part_base.html:55 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:58 +#: part/templates/part/part_base.html:59 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:73 +#: part/templates/part/part_base.html:74 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:76 +#: part/templates/part/part_base.html:77 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:79 +#: part/templates/part/part_base.html:80 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:82 +#: part/templates/part/part_base.html:83 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:122 templates/js/table_filters.js:134 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:135 templates/InvenTree/index.html:130 +#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:142 +#: part/templates/part/part_base.html:143 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:149 +#: part/templates/part/part_base.html:150 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:164 templates/js/bom.js:296 +#: part/templates/part/part_base.html:165 templates/js/bom.js:300 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:170 templates/js/part.js:417 +#: part/templates/part/part_base.html:171 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:249 +#: part/templates/part/part_base.html:250 msgid "Calculate" msgstr "" #: part/templates/part/part_pricing.html:8 -msgid "Pricing information for:" +#, python-format +msgid "Pricing information for:
%(part)s." msgstr "" -#: part/templates/part/part_pricing.html:24 +#: part/templates/part/part_pricing.html:23 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:28 -#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:27 +#: part/templates/part/part_pricing.html:53 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:34 -#: part/templates/part/part_pricing.html:60 +#: part/templates/part/part_pricing.html:33 +#: part/templates/part/part_pricing.html:59 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:42 +#: part/templates/part/part_pricing.html:41 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:50 +#: part/templates/part/part_pricing.html:49 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:68 +#: part/templates/part/part_pricing.html:67 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:75 +#: part/templates/part/part_pricing.html:74 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:85 +#: part/templates/part/part_pricing.html:84 msgid "No pricing information is available for this part." msgstr "" @@ -4234,6 +4473,36 @@ msgstr "" msgid "Select from existing images" msgstr "" +#: part/templates/part/partial_delete.html:7 +#, python-format +msgid "Are you sure you want to delete part '%(full_name)s'?" +msgstr "" + +#: part/templates/part/partial_delete.html:12 +#, python-format +msgid "This part is used in BOMs for %(count)s other parts. If you delete this part, the BOMs for the following parts will be updated" +msgstr "" + +#: part/templates/part/partial_delete.html:22 +#, python-format +msgid "There are %(count)s stock entries defined for this part. If you delete this part, the following stock entries will also be deleted:" +msgstr "" + +#: part/templates/part/partial_delete.html:33 +#, python-format +msgid "There are %(count)s manufacturers defined for this part. If you delete this part, the following manufacturer parts will also be deleted:" +msgstr "" + +#: part/templates/part/partial_delete.html:44 +#, python-format +msgid "There are %(count)s suppliers defined for this part. If you delete this part, the following supplier parts will also be deleted:" +msgstr "" + +#: part/templates/part/partial_delete.html:55 +#, python-format +msgid "There are %(count)s unique parts tracked for '%(full_name)s'. Deleting this part will permanently remove this tracking information." +msgstr "" + #: part/templates/part/related.html:18 msgid "Add Related" msgstr "" @@ -4259,38 +4528,23 @@ msgid "Part Stock" msgstr "" #: part/templates/part/stock.html:16 -msgid "Showing stock for all variants of" +#, python-format +msgid "Showing stock for all variants of %(full_name)s" msgstr "" #: part/templates/part/stock_count.html:7 templates/js/bom.js:239 -#: templates/js/part.js:421 +#: templates/js/part.js:422 msgid "No Stock" msgstr "" -#: part/templates/part/stock_count.html:9 templates/InvenTree/index.html:129 +#: part/templates/part/stock_count.html:9 templates/InvenTree/index.html:130 msgid "Low Stock" msgstr "" -#: part/templates/part/subcategories.html:5 -msgid "Child Categories" -msgstr "" - #: part/templates/part/supplier.html:10 msgid "Part Suppliers" msgstr "" -#: part/templates/part/supplier.html:22 -msgid "Delete supplier parts" -msgstr "" - -#: part/templates/part/supplier.html:51 -msgid "Create new supplier" -msgstr "" - -#: part/templates/part/supplier.html:57 -msgid "Create new manufacturer" -msgstr "" - #: part/templates/part/track.html:10 msgid "Part Tracking" msgstr "" @@ -4304,7 +4558,8 @@ msgid "Create new part variant" msgstr "" #: part/templates/part/variant_part.html:10 -msgid "Create a new variant of template" +#, python-format +msgid "Create a new variant of template '%(full_name)s'." msgstr "" #: part/templates/part/variants.html:19 @@ -4452,75 +4707,75 @@ msgstr "" msgid "Specify quantity" msgstr "" -#: part/views.py:1933 +#: part/views.py:1939 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1940 +#: part/views.py:1946 msgid "Part was deleted" msgstr "" -#: part/views.py:1949 +#: part/views.py:1955 msgid "Part Pricing" msgstr "" -#: part/views.py:2063 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2073 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2080 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2088 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2138 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2152 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2212 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2250 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2308 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2409 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2465 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2484 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2554 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2610 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -4622,17 +4877,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1640 +#: stock/models.py:1643 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1646 +#: stock/models.py:1649 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:909 +#: templates/js/order.js:195 templates/js/stock.js:986 msgid "Date" msgstr "" @@ -4654,8 +4909,8 @@ msgstr "" msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:473 -#: stock/templates/stock/item_base.html:349 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 +#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -4668,9 +4923,7 @@ msgid "Enter unique serial numbers (or leave blank)" msgstr "" #: stock/forms.py:169 -msgid "" -"Destination for serialized stock (by default, will remain in current " -"location)" +msgid "Destination for serialized stock (by default, will remain in current location)" msgstr "" #: stock/forms.py:171 @@ -4689,7 +4942,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:111 +#: stock/forms.py:267 templates/js/table_filters.js:70 +#: templates/js/table_filters.js:133 msgid "Include sublocations" msgstr "" @@ -4745,11 +4999,11 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:511 +#: stock/models.py:54 stock/models.py:513 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:512 +#: stock/models.py:55 stock/models.py:514 msgid "Select Owner" msgstr "" @@ -4786,203 +5040,202 @@ msgstr "" msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:363 +#: stock/models.py:365 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:372 +#: stock/models.py:374 msgid "Base part" msgstr "" -#: stock/models.py:381 +#: stock/models.py:383 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:386 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:389 +#: stock/models.py:391 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:396 +#: stock/models.py:398 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:401 stock/templates/stock/item_base.html:255 +#: stock/models.py:403 stock/templates/stock/item_base.html:259 msgid "Installed In" msgstr "" -#: stock/models.py:404 +#: stock/models.py:406 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:420 +#: stock/models.py:422 msgid "Serial number for this item" msgstr "" -#: stock/models.py:432 +#: stock/models.py:434 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:436 +#: stock/models.py:438 msgid "Stock Quantity" msgstr "" -#: stock/models.py:445 +#: stock/models.py:447 msgid "Source Build" msgstr "" -#: stock/models.py:447 +#: stock/models.py:449 msgid "Build for this stock item" msgstr "" -#: stock/models.py:458 +#: stock/models.py:460 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:461 +#: stock/models.py:463 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:467 +#: stock/models.py:469 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:474 -msgid "" -"Expiry date for stock item. Stock will be considered expired after this date" +#: stock/models.py:476 +msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:487 +#: stock/models.py:489 msgid "Delete on deplete" msgstr "" -#: stock/models.py:487 +#: stock/models.py:489 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:497 stock/templates/stock/item_notes.html:13 +#: stock/models.py:499 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:507 +#: stock/models.py:509 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:612 +#: stock/models.py:614 msgid "Assigned to Customer" msgstr "" -#: stock/models.py:614 +#: stock/models.py:616 msgid "Manually assigned to customer" msgstr "" -#: stock/models.py:627 +#: stock/models.py:629 msgid "Returned from customer" msgstr "" -#: stock/models.py:629 +#: stock/models.py:631 msgid "Returned to location" msgstr "" -#: stock/models.py:789 +#: stock/models.py:792 msgid "Installed into stock item" msgstr "" -#: stock/models.py:797 +#: stock/models.py:800 msgid "Installed stock item" msgstr "" -#: stock/models.py:821 +#: stock/models.py:824 msgid "Uninstalled stock item" msgstr "" -#: stock/models.py:840 +#: stock/models.py:843 msgid "Uninstalled into location" msgstr "" -#: stock/models.py:941 +#: stock/models.py:944 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:947 +#: stock/models.py:950 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:953 +#: stock/models.py:956 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:956 +#: stock/models.py:959 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:959 +#: stock/models.py:962 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:991 +#: stock/models.py:994 msgid "Add serial number" msgstr "" -#: stock/models.py:994 +#: stock/models.py:997 #, python-brace-format msgid "Serialized {n} items" msgstr "" -#: stock/models.py:1072 +#: stock/models.py:1075 msgid "Split from existing stock" msgstr "" -#: stock/models.py:1110 +#: stock/models.py:1113 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1553 +#: stock/models.py:1556 msgid "Title" msgstr "" -#: stock/models.py:1553 +#: stock/models.py:1556 msgid "Tracking entry title" msgstr "" -#: stock/models.py:1555 +#: stock/models.py:1558 msgid "Entry notes" msgstr "" -#: stock/models.py:1557 +#: stock/models.py:1560 msgid "Link to external page for further information" msgstr "" -#: stock/models.py:1617 +#: stock/models.py:1620 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1623 +#: stock/models.py:1626 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1641 +#: stock/models.py:1644 msgid "Test name" msgstr "" -#: stock/models.py:1647 templates/js/table_filters.js:190 +#: stock/models.py:1650 templates/js/table_filters.js:212 msgid "Test result" msgstr "" -#: stock/models.py:1653 +#: stock/models.py:1656 msgid "Test output value" msgstr "" -#: stock/models.py:1660 +#: stock/models.py:1663 msgid "Test result attachment" msgstr "" -#: stock/models.py:1666 +#: stock/models.py:1669 msgid "Test notes" msgstr "" @@ -4999,9 +5252,7 @@ msgid "Stock Item Attachments" msgstr "" #: stock/templates/stock/item_base.html:24 -msgid "" -"You are not in the list of owners of this item. This stock item cannot be " -"edited." +msgid "You are not in the list of owners of this item. This stock item cannot be edited." msgstr "" #: stock/templates/stock/item_base.html:31 @@ -5016,156 +5267,157 @@ msgstr "" msgid "This stock item has not passed all required tests" msgstr "" -#: stock/templates/stock/item_base.html:51 -msgid "This stock item is allocated to Sales Order" +#: stock/templates/stock/item_base.html:53 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" msgstr "" -#: stock/templates/stock/item_base.html:57 -msgid "This stock item is allocated to Build" -msgstr "" - -#: stock/templates/stock/item_base.html:63 -msgid "" -"This stock item is serialized - it has a unique serial number and the " -"quantity cannot be adjusted." +#: stock/templates/stock/item_base.html:61 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" msgstr "" #: stock/templates/stock/item_base.html:67 -msgid "This stock item cannot be deleted as it has child items" +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." msgstr "" #: stock/templates/stock/item_base.html:71 -msgid "" -"This stock item will be automatically deleted when all stock is depleted." +msgid "This stock item cannot be deleted as it has child items" msgstr "" -#: stock/templates/stock/item_base.html:91 -#: stock/templates/stock/item_base.html:353 templates/js/table_filters.js:123 -msgid "Expired" +#: stock/templates/stock/item_base.html:75 +msgid "This stock item will be automatically deleted when all stock is depleted." msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:355 templates/js/table_filters.js:128 +#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +msgid "Expired" +msgstr "" + +#: stock/templates/stock/item_base.html:99 +#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:132 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:134 +#: stock/templates/stock/item_base.html:138 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:143 +#: stock/templates/stock/item_base.html:147 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:151 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:156 +#: stock/templates/stock/item_base.html:160 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:160 -#: stock/templates/stock/location.html:58 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:163 templates/stock_table.html:53 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:166 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:169 +#: stock/templates/stock/item_base.html:173 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:177 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:176 +#: stock/templates/stock/item_base.html:180 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:183 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:183 templates/js/stock.js:1222 +#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:187 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:192 -#: stock/templates/stock/location.html:55 +#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:195 +#: stock/templates/stock/item_base.html:199 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:198 +#: stock/templates/stock/item_base.html:202 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:200 +#: stock/templates/stock/item_base.html:204 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:203 +#: stock/templates/stock/item_base.html:207 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:215 +#: stock/templates/stock/item_base.html:219 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:274 templates/js/build.js:442 +#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:281 +#: stock/templates/stock/item_base.html:285 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:323 +#: stock/templates/stock/item_base.html:327 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:353 -msgid "This StockItem expired on" -msgstr "" - -#: stock/templates/stock/item_base.html:355 -msgid "This StockItem expires on" -msgstr "" - -#: stock/templates/stock/item_base.html:362 templates/js/stock.js:662 -msgid "Last Updated" -msgstr "" - -#: stock/templates/stock/item_base.html:367 -msgid "Last Stocktake" +#: stock/templates/stock/item_base.html:369 +#, python-format +msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" #: stock/templates/stock/item_base.html:371 +#, python-format +msgid "This StockItem expires on %(item.expiry_date)s" +msgstr "" + +#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +msgid "Last Updated" +msgstr "" + +#: stock/templates/stock/item_base.html:383 +msgid "Last Stocktake" +msgstr "" + +#: stock/templates/stock/item_base.html:387 msgid "No stocktake performed" msgstr "" @@ -5181,6 +5433,11 @@ msgstr "" msgid "Are you sure you want to delete this stock item?" msgstr "" +#: stock/templates/stock/item_delete.html:12 +#, python-format +msgid "This will remove %(qty)s units of %(full_name)s from stock." +msgstr "" + #: stock/templates/stock/item_install.html:7 msgid "Install another StockItem into this item." msgstr "" @@ -5223,54 +5480,55 @@ msgstr "" msgid "Add Test Data" msgstr "" -#: stock/templates/stock/location.html:13 -msgid "" -"You are not in the list of owners of this location. This stock location " -"cannot be edited." +#: stock/templates/stock/location.html:20 +msgid "You are not in the list of owners of this location. This stock location cannot be edited." msgstr "" -#: stock/templates/stock/location.html:30 +#: stock/templates/stock/location.html:37 msgid "All stock items" msgstr "" -#: stock/templates/stock/location.html:48 +#: stock/templates/stock/location.html:55 msgid "Check-in Items" msgstr "" -#: stock/templates/stock/location.html:64 +#: stock/templates/stock/location.html:71 msgid "Location actions" msgstr "" -#: stock/templates/stock/location.html:66 +#: stock/templates/stock/location.html:73 msgid "Edit location" msgstr "" -#: stock/templates/stock/location.html:68 +#: stock/templates/stock/location.html:75 msgid "Delete location" msgstr "" -#: stock/templates/stock/location.html:80 +#: stock/templates/stock/location.html:87 msgid "Location Details" msgstr "" -#: stock/templates/stock/location.html:85 +#: stock/templates/stock/location.html:92 msgid "Location Path" msgstr "" -#: stock/templates/stock/location.html:90 +#: stock/templates/stock/location.html:97 msgid "Location Description" msgstr "" -#: stock/templates/stock/location.html:95 +#: stock/templates/stock/location.html:102 +#: stock/templates/stock/location_navbar.html:11 +#: stock/templates/stock/location_navbar.html:18 +#: stock/templates/stock/sublocation.html:16 msgid "Sublocations" msgstr "" -#: stock/templates/stock/location.html:105 +#: stock/templates/stock/location.html:112 msgid "Stock Details" msgstr "" -#: stock/templates/stock/location.html:110 templates/InvenTree/search.html:263 -#: templates/stats.html:76 users/models.py:39 +#: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5278,18 +5536,6 @@ msgstr "" msgid "Are you sure you want to delete this stock location?" msgstr "" -#: stock/templates/stock/location_list.html:6 -msgid "Sub-Locations" -msgstr "" - -#. Translators: pluralize with counter -#: stock/templates/stock/location_list.html:17 -#, python-format -msgid "%(counter)s Item" -msgid_plural "%(counter)s Items" -msgstr[0] "" -msgstr[1] "" - #: stock/templates/stock/navbar.html:11 msgid "Stock Item Tracking" msgstr "" @@ -5314,7 +5560,7 @@ msgstr "" msgid "Remove item" msgstr "" -#: stock/templates/stock/stock_app_base.html:15 +#: stock/templates/stock/stock_app_base.html:16 msgid "Loading..." msgstr "" @@ -5327,7 +5573,8 @@ msgid "Convert Stock Item" msgstr "" #: stock/templates/stock/stockitem_convert.html:8 -msgid "This stock item is current an instance of " +#, python-format +msgid "This stock item is current an instance of %(part)s" msgstr "" #: stock/templates/stock/stockitem_convert.html:9 @@ -5338,6 +5585,18 @@ msgstr "" msgid "This action cannot be easily undone" msgstr "" +#: stock/templates/stock/sublocation.html:23 templates/stock_table.html:37 +msgid "Printing Actions" +msgstr "" + +#: stock/templates/stock/sublocation.html:27 templates/stock_table.html:41 +msgid "Print labels" +msgstr "" + +#: stock/templates/stock/tracking_delete.html:6 +msgid "Are you sure you want to delete this stock tracking entry?" +msgstr "" + #: stock/views.py:123 msgid "Edit Stock Location" msgstr "" @@ -5455,7 +5714,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:178 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5517,7 +5776,7 @@ msgstr "" msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:210 +#: stock/views.py:1543 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" @@ -5565,74 +5824,99 @@ msgstr "" msgid "The requested page does not exist" msgstr "" -#: templates/InvenTree/index.html:6 +#: templates/InvenTree/index.html:7 msgid "Index" msgstr "" -#: templates/InvenTree/index.html:97 +#: templates/InvenTree/index.html:98 msgid "Starred Parts" msgstr "" -#: templates/InvenTree/index.html:98 +#: templates/InvenTree/index.html:99 msgid "Latest Parts" msgstr "" -#: templates/InvenTree/index.html:99 +#: templates/InvenTree/index.html:100 msgid "BOM Waiting Validation" msgstr "" -#: templates/InvenTree/index.html:128 +#: templates/InvenTree/index.html:129 msgid "Recently Updated" msgstr "" -#: templates/InvenTree/index.html:144 +#: templates/InvenTree/index.html:145 msgid "Expired Stock" msgstr "" -#: templates/InvenTree/index.html:145 +#: templates/InvenTree/index.html:146 msgid "Stale Stock" msgstr "" -#: templates/InvenTree/index.html:183 +#: templates/InvenTree/index.html:184 msgid "Build Orders In Progress" msgstr "" -#: templates/InvenTree/index.html:184 +#: templates/InvenTree/index.html:185 msgid "Overdue Build Orders" msgstr "" -#: templates/InvenTree/index.html:205 +#: templates/InvenTree/index.html:206 msgid "Outstanding Purchase Orders" msgstr "" -#: templates/InvenTree/index.html:206 +#: templates/InvenTree/index.html:207 msgid "Overdue Purchase Orders" msgstr "" -#: templates/InvenTree/index.html:228 +#: templates/InvenTree/index.html:229 msgid "Outstanding Sales Orders" msgstr "" -#: templates/InvenTree/index.html:229 +#: templates/InvenTree/index.html:230 msgid "Overdue Sales Orders" msgstr "" -#: templates/InvenTree/search.html:7 templates/InvenTree/search.html:13 +#: templates/InvenTree/search.html:8 templates/InvenTree/search.html:14 msgid "Search Results" msgstr "" -#: templates/InvenTree/search.html:23 +#: templates/InvenTree/search.html:24 msgid "Enter a search query" msgstr "" -#: templates/InvenTree/search.html:252 templates/js/stock.js:300 +#: templates/InvenTree/search.html:268 templates/js/stock.js:300 msgid "Shipped to customer" msgstr "" -#: templates/InvenTree/search.html:255 templates/js/stock.js:310 +#: templates/InvenTree/search.html:271 templates/js/stock.js:310 msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5663,7 +5947,7 @@ msgstr "" msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:26 +#: templates/InvenTree/settings/global.html:27 msgid "Barcode Settings" msgstr "" @@ -5703,8 +5987,8 @@ msgstr "" msgid "Edit setting" msgstr "" -#: templates/InvenTree/settings/settings.html:7 -#: templates/InvenTree/settings/settings.html:13 templates/navbar.html:78 +#: templates/InvenTree/settings/settings.html:8 +#: templates/InvenTree/settings/settings.html:14 templates/navbar.html:84 msgid "Settings" msgstr "" @@ -5716,7 +6000,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:48 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5730,7 +6014,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5749,24 +6033,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "" -"\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected " -"color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -5776,7 +6042,7 @@ msgid "Change Password" msgstr "" #: templates/InvenTree/settings/user.html:28 -#: templates/registration/login.html:58 +#: templates/registration/login.html:59 msgid "Username" msgstr "" @@ -5829,13 +6095,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -5913,8 +6189,7 @@ msgid "Link Barcode to Stock Item" msgstr "" #: templates/js/barcode.js:311 -msgid "" -"This will remove the association between this stock item and the barcode" +msgid "This will remove the association between this stock item and the barcode" msgstr "" #: templates/js/barcode.js:317 @@ -5961,7 +6236,7 @@ msgstr "" msgid "Barcode does not match a valid location" msgstr "" -#: templates/js/bom.js:175 templates/js/build.js:934 +#: templates/js/bom.js:175 templates/js/build.js:994 msgid "Open subassembly" msgstr "" @@ -5969,77 +6244,88 @@ msgstr "" msgid "No pricing available" msgstr "" -#: templates/js/bom.js:286 templates/js/bom.js:372 +#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/filters.js:397 +msgid "true" +msgstr "" + +#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/filters.js:398 +msgid "false" +msgstr "" + +#: templates/js/bom.js:290 templates/js/bom.js:376 msgid "View BOM" msgstr "" -#: templates/js/bom.js:346 +#: templates/js/bom.js:350 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:348 +#: templates/js/bom.js:352 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:354 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:356 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:443 templates/js/build.js:305 templates/js/build.js:1032 +#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" -#: templates/js/build.js:56 +#: templates/js/build.js:62 msgid "Auto-allocate stock items to this output" msgstr "" -#: templates/js/build.js:62 -msgid "Complete build output" -msgstr "" - -#: templates/js/build.js:71 +#: templates/js/build.js:70 msgid "Unallocate stock from build output" msgstr "" -#: templates/js/build.js:77 +#: templates/js/build.js:80 +msgid "Complete build output" +msgstr "" + +#: templates/js/build.js:89 msgid "Delete build output" msgstr "" -#: templates/js/build.js:209 templates/stock_table.html:20 +#: templates/js/build.js:243 templates/stock_table.html:20 msgid "New Stock Item" msgstr "" -#: templates/js/build.js:493 +#: templates/js/build.js:549 msgid "Required Part" msgstr "" -#: templates/js/build.js:514 +#: templates/js/build.js:570 msgid "Quantity Per" msgstr "" -#: templates/js/build.js:582 templates/js/build.js:996 -#: templates/stock_table.html:57 +#: templates/js/build.js:638 templates/js/build.js:1056 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" -#: templates/js/build.js:632 +#: templates/js/build.js:691 msgid "No builds matching query" msgstr "" -#: templates/js/build.js:649 templates/js/part.js:323 templates/js/stock.js:511 -#: templates/js/stock.js:1254 +#: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 +#: templates/js/stock.js:511 templates/js/stock.js:938 +#: templates/js/stock.js:1331 msgid "Select" msgstr "" -#: templates/js/build.js:669 +#: templates/js/build.js:728 msgid "Build order is overdue" msgstr "" -#: templates/js/build.js:767 +#: templates/js/build.js:827 msgid "No parts allocated for" msgstr "" @@ -6056,17 +6342,23 @@ msgid "No company information found" msgstr "" #: templates/js/company.js:129 -msgid "No supplier parts found" +msgid "No manufacturer parts found" msgstr "" -#: templates/js/company.js:147 templates/js/part.js:59 templates/js/part.js:144 +#: templates/js/company.js:148 templates/js/company.js:246 +#: templates/js/part.js:60 templates/js/part.js:145 msgid "Template part" msgstr "" -#: templates/js/company.js:151 templates/js/part.js:63 templates/js/part.js:148 +#: templates/js/company.js:152 templates/js/company.js:250 +#: templates/js/part.js:64 templates/js/part.js:149 msgid "Assembled part" msgstr "" +#: templates/js/company.js:227 +msgid "No supplier parts found" +msgstr "" + #: templates/js/filters.js:193 msgid "Select filter" msgstr "" @@ -6148,11 +6440,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6233,59 +6520,63 @@ msgstr "" msgid "No sales orders found" msgstr "" -#: templates/js/part.js:51 templates/js/part.js:136 +#: templates/js/part.js:52 templates/js/part.js:137 msgid "Trackable part" msgstr "" -#: templates/js/part.js:55 templates/js/part.js:140 +#: templates/js/part.js:56 templates/js/part.js:141 msgid "Virtual part" msgstr "" -#: templates/js/part.js:67 +#: templates/js/part.js:68 msgid "Starred part" msgstr "" -#: templates/js/part.js:71 +#: templates/js/part.js:72 msgid "Salable part" msgstr "" -#: templates/js/part.js:185 +#: templates/js/part.js:186 msgid "No variants found" msgstr "" -#: templates/js/part.js:271 templates/js/part.js:451 +#: templates/js/part.js:272 templates/js/part.js:452 msgid "No parts found" msgstr "" -#: templates/js/part.js:390 +#: templates/js/part.js:391 msgid "No category" msgstr "" -#: templates/js/part.js:408 templates/js/table_filters.js:296 +#: templates/js/part.js:409 templates/js/table_filters.js:318 msgid "Low stock" msgstr "" -#: templates/js/part.js:511 +#: templates/js/part.js:571 templates/js/stock.js:962 +msgid "Path" +msgstr "" + +#: templates/js/part.js:588 msgid "YES" msgstr "" -#: templates/js/part.js:513 +#: templates/js/part.js:590 msgid "NO" msgstr "" -#: templates/js/part.js:547 +#: templates/js/part.js:624 msgid "No test templates matching query" msgstr "" -#: templates/js/part.js:598 templates/js/stock.js:75 +#: templates/js/part.js:675 templates/js/stock.js:75 msgid "Edit test result" msgstr "" -#: templates/js/part.js:599 templates/js/stock.js:76 +#: templates/js/part.js:676 templates/js/stock.js:76 msgid "Delete test result" msgstr "" -#: templates/js/part.js:605 +#: templates/js/part.js:682 msgid "This test is defined for a parent part" msgstr "" @@ -6399,6 +6690,18 @@ msgstr "" msgid "No stock items matching query" msgstr "" +#: templates/js/stock.js:357 +msgid "items" +msgstr "" + +#: templates/js/stock.js:449 +msgid "batches" +msgstr "" + +#: templates/js/stock.js:476 +msgid "locations" +msgstr "" + #: templates/js/stock.js:478 msgid "Undefined location" msgstr "" @@ -6443,7 +6746,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:116 +#: templates/js/stock.js:620 templates/js/table_filters.js:138 msgid "Depleted" msgstr "" @@ -6467,31 +6770,31 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:973 +#: templates/js/stock.js:1050 msgid "No user information" msgstr "" -#: templates/js/stock.js:983 +#: templates/js/stock.js:1060 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:984 +#: templates/js/stock.js:1061 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1093 +#: templates/js/stock.js:1170 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1192 +#: templates/js/stock.js:1269 msgid "Serial" msgstr "" -#: templates/js/stock.js:1285 templates/js/table_filters.js:149 +#: templates/js/stock.js:1362 templates/js/table_filters.js:171 msgid "Installed" msgstr "" -#: templates/js/stock.js:1310 +#: templates/js/stock.js:1387 msgid "Install item" msgstr "" @@ -6503,148 +6806,153 @@ msgstr "" msgid "Validated" msgstr "" -#: templates/js/table_filters.js:70 templates/js/table_filters.js:159 -msgid "Is Serialized" -msgstr "" - -#: templates/js/table_filters.js:73 templates/js/table_filters.js:166 -msgid "Serial number GTE" -msgstr "" - -#: templates/js/table_filters.js:74 templates/js/table_filters.js:167 -msgid "Serial number greater than or equal to" -msgstr "" - -#: templates/js/table_filters.js:77 templates/js/table_filters.js:170 -msgid "Serial number LTE" -msgstr "" - -#: templates/js/table_filters.js:78 templates/js/table_filters.js:171 -msgid "Serial number less than or equal to" +#: templates/js/table_filters.js:71 +msgid "Include locations" msgstr "" #: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:162 templates/js/table_filters.js:163 -msgid "Serial number" -msgstr "" - -#: templates/js/table_filters.js:86 templates/js/table_filters.js:180 -msgid "Batch code" -msgstr "" - -#: templates/js/table_filters.js:96 templates/js/table_filters.js:263 -msgid "Active parts" -msgstr "" - -#: templates/js/table_filters.js:97 -msgid "Show stock for active parts" -msgstr "" - -#: templates/js/table_filters.js:102 -msgid "Part is an assembly" -msgstr "" - -#: templates/js/table_filters.js:106 -msgid "Is allocated" -msgstr "" - -#: templates/js/table_filters.js:107 -msgid "Item has been allocated" -msgstr "" - -#: templates/js/table_filters.js:112 -msgid "Include stock in sublocations" -msgstr "" - -#: templates/js/table_filters.js:117 -msgid "Show stock items which are depleted" -msgstr "" - -#: templates/js/table_filters.js:124 -msgid "Show stock items which have expired" -msgstr "" - -#: templates/js/table_filters.js:129 -msgid "Show stock which is close to expiring" -msgstr "" - -#: templates/js/table_filters.js:135 -msgid "Show items which are in stock" -msgstr "" - -#: templates/js/table_filters.js:139 -msgid "In Production" -msgstr "" - -#: templates/js/table_filters.js:140 -msgid "Show items which are in production" -msgstr "" - -#: templates/js/table_filters.js:144 -msgid "Include Variants" -msgstr "" - -#: templates/js/table_filters.js:145 -msgid "Include stock items for variant parts" -msgstr "" - -#: templates/js/table_filters.js:150 -msgid "Show stock items which are installed in another item" -msgstr "" - -#: templates/js/table_filters.js:154 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:155 -msgid "Show items which have been assigned to a customer" -msgstr "" - -#: templates/js/table_filters.js:175 templates/js/table_filters.js:176 -msgid "Stock status" -msgstr "" - -#: templates/js/table_filters.js:209 -msgid "Build status" -msgstr "" - -#: templates/js/table_filters.js:228 templates/js/table_filters.js:245 -msgid "Order status" -msgstr "" - -#: templates/js/table_filters.js:233 templates/js/table_filters.js:250 -msgid "Outstanding" -msgstr "" - -#: templates/js/table_filters.js:273 +#: templates/js/table_filters.js:295 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:274 +#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +msgid "Is Serialized" +msgstr "" + +#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +msgid "Serial number GTE" +msgstr "" + +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +msgid "Serial number greater than or equal to" +msgstr "" + +#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +msgid "Serial number LTE" +msgstr "" + +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +msgid "Serial number less than or equal to" +msgstr "" + +#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 +#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +msgid "Serial number" +msgstr "" + +#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +msgid "Batch code" +msgstr "" + +#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +msgid "Active parts" +msgstr "" + +#: templates/js/table_filters.js:119 +msgid "Show stock for active parts" +msgstr "" + +#: templates/js/table_filters.js:124 +msgid "Part is an assembly" +msgstr "" + +#: templates/js/table_filters.js:128 +msgid "Is allocated" +msgstr "" + +#: templates/js/table_filters.js:129 +msgid "Item has been allocated" +msgstr "" + +#: templates/js/table_filters.js:134 +msgid "Include stock in sublocations" +msgstr "" + +#: templates/js/table_filters.js:139 +msgid "Show stock items which are depleted" +msgstr "" + +#: templates/js/table_filters.js:146 +msgid "Show stock items which have expired" +msgstr "" + +#: templates/js/table_filters.js:151 +msgid "Show stock which is close to expiring" +msgstr "" + +#: templates/js/table_filters.js:157 +msgid "Show items which are in stock" +msgstr "" + +#: templates/js/table_filters.js:161 +msgid "In Production" +msgstr "" + +#: templates/js/table_filters.js:162 +msgid "Show items which are in production" +msgstr "" + +#: templates/js/table_filters.js:166 +msgid "Include Variants" +msgstr "" + +#: templates/js/table_filters.js:167 +msgid "Include stock items for variant parts" +msgstr "" + +#: templates/js/table_filters.js:172 +msgid "Show stock items which are installed in another item" +msgstr "" + +#: templates/js/table_filters.js:176 +msgid "Sent to customer" +msgstr "" + +#: templates/js/table_filters.js:177 +msgid "Show items which have been assigned to a customer" +msgstr "" + +#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +msgid "Stock status" +msgstr "" + +#: templates/js/table_filters.js:231 +msgid "Build status" +msgstr "" + +#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +msgid "Order status" +msgstr "" + +#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +msgid "Outstanding" +msgstr "" + +#: templates/js/table_filters.js:296 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:278 +#: templates/js/table_filters.js:300 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:279 +#: templates/js/table_filters.js:301 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:284 +#: templates/js/table_filters.js:306 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:292 +#: templates/js/table_filters.js:314 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:308 +#: templates/js/table_filters.js:330 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:320 +#: templates/js/table_filters.js:342 msgid "Purchasable" msgstr "" @@ -6705,6 +7013,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6717,19 +7029,19 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:71 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" -#: templates/navbar.html:73 +#: templates/navbar.html:79 msgid "Logout" msgstr "" -#: templates/navbar.html:75 templates/registration/login.html:89 +#: templates/navbar.html:81 templates/registration/login.html:90 msgid "Login" msgstr "" -#: templates/navbar.html:94 +#: templates/navbar.html:104 msgid "About InvenTree" msgstr "" @@ -6737,73 +7049,67 @@ msgstr "" msgid "QR data not provided" msgstr "" -#: templates/registration/logged_out.html:50 +#: templates/registration/logged_out.html:51 msgid "You have been logged out" msgstr "" -#: templates/registration/logged_out.html:51 -#: templates/registration/password_reset_complete.html:51 -#: templates/registration/password_reset_done.html:58 +#: templates/registration/logged_out.html:52 +#: templates/registration/password_reset_complete.html:52 +#: templates/registration/password_reset_done.html:59 msgid "Return to login screen" msgstr "" -#: templates/registration/login.html:64 +#: templates/registration/login.html:65 msgid "Enter username" msgstr "" -#: templates/registration/login.html:70 +#: templates/registration/login.html:71 msgid "Password" msgstr "" -#: templates/registration/login.html:83 +#: templates/registration/login.html:84 msgid "Username / password combination is incorrect" msgstr "" -#: templates/registration/login.html:95 -#: templates/registration/password_reset_form.html:51 +#: templates/registration/login.html:96 +#: templates/registration/password_reset_form.html:52 msgid "Forgotten your password?" msgstr "" -#: templates/registration/login.html:95 +#: templates/registration/login.html:96 msgid "Click here to reset" msgstr "" -#: templates/registration/password_reset_complete.html:50 +#: templates/registration/password_reset_complete.html:51 msgid "Password reset complete" msgstr "" -#: templates/registration/password_reset_confirm.html:52 -#: templates/registration/password_reset_confirm.html:56 +#: templates/registration/password_reset_confirm.html:53 +#: templates/registration/password_reset_confirm.html:57 msgid "Change password" msgstr "" -#: templates/registration/password_reset_confirm.html:60 -msgid "" -"The password reset link was invalid, possibly because it has already been " -"used. Please request a new password reset." +#: templates/registration/password_reset_confirm.html:61 +msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." msgstr "" -#: templates/registration/password_reset_done.html:51 -msgid "" -"We've emailed you instructions for setting your password, if an account " -"exists with the email you entered. You should receive them shortly." +#: templates/registration/password_reset_done.html:52 +msgid "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." msgstr "" -#: templates/registration/password_reset_done.html:54 -msgid "" -"If you don't receive an email, please make sure you've entered the address " -"you registered with, and check your spam folder." -msgstr "" - -#: templates/registration/password_reset_form.html:52 -msgid "Enter your email address below." +#: templates/registration/password_reset_done.html:55 +msgid "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." msgstr "" #: templates/registration/password_reset_form.html:53 +msgid "Enter your email address below." +msgstr "" + +#: templates/registration/password_reset_form.html:54 msgid "An email will be sent with password reset instructions." msgstr "" -#: templates/registration/password_reset_form.html:58 +#: templates/registration/password_reset_form.html:59 msgid "Send email" msgstr "" @@ -6851,58 +7157,58 @@ msgstr "" msgid "Barcode Actions" msgstr "" -#: templates/stock_table.html:36 -msgid "Printing Actions" -msgstr "" - -#: templates/stock_table.html:40 -msgid "Print labels" -msgstr "" - -#: templates/stock_table.html:42 +#: templates/stock_table.html:43 msgid "Print test reports" msgstr "" -#: templates/stock_table.html:53 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:61 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:61 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" +#: templates/yesnolabel.html:4 +msgid "Yes" +msgstr "" + +#: templates/yesnolabel.html:6 +msgid "No" +msgstr "" + #: users/admin.py:64 msgid "Users" msgstr "" @@ -6927,34 +7233,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:165 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:173 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:176 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:176 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:178 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:180 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:180 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:182 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.mo b/InvenTree/locale/es/LC_MESSAGES/django.mo index 71cbdf3e9d8d54be31066ec4ad8628bc2c1f2845..2343941a2a4bb6c1a1b8e2cf6c46bc2766f09be7 100644 GIT binary patch delta 91 zcmeyvbew5|3M21CRgH-;TAoG*MuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= mK#{!k(!}&s-H_D8Tq}j(g2cSc;taU3l|pK9yle2puk8Tgg&mv# delta 161 zcmX@k^oMDJ3Zv6RRSo_CM`v$GcUOfl*Pvief4_;oTJ@2xjzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3OJ$+qu!%~ZiGxPJT6bvU`C\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,34 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/fr/LC_MESSAGES/django.mo b/InvenTree/locale/fr/LC_MESSAGES/django.mo index 2c90dd0c81aca562856271a6885816b565885734..71c5e169163d4e95748145ef537da8839930b0c2 100644 GIT binary patch delta 90 zcmey(bd+g=3M2PKRgH-;S{_CQMuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= lK#{!k(!}&s-H_D8Tq^~)qSUZ2-TA9Tflo delta 161 zcmX@g^qXmd3ZvshRSo_CM`v$GcUOfl*Pvief4_;oTJ@2xjzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3OJ$+qu!%~ZiGxPJT6bvVxF9QHO CfH83Z diff --git a/InvenTree/locale/fr/LC_MESSAGES/django.po b/InvenTree/locale/fr/LC_MESSAGES/django.po index f344b4140c..ae5d861fa2 100644 --- a/InvenTree/locale/fr/LC_MESSAGES/django.po +++ b/InvenTree/locale/fr/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-21 09:17+0000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: 2021-04-21 09:33\n" "Last-Translator: \n" "Language-Team: French\n" @@ -67,35 +67,36 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:375 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:378 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:399 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:403 InvenTree/helpers.py:406 InvenTree/helpers.py:409 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:414 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:422 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:426 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" @@ -140,7 +141,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 @@ -165,23 +166,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:496 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:497 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" @@ -375,16 +376,16 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1227 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 #: build/templates/build/detail.html:31 common/models.py:703 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:200 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 @@ -458,7 +459,7 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:445 +#: build/templates/build/detail.html:59 order/models.py:455 #: order/templates/order/receive_parts.html:24 #: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 @@ -508,7 +509,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -516,8 +517,8 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:195 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 #: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 @@ -540,10 +541,10 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:669 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 #: part/models.py:1876 part/models.py:1888 part/models.py:1906 @@ -628,7 +629,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" @@ -678,9 +679,9 @@ msgstr "" #: company/models.py:135 company/models.py:501 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:234 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 @@ -713,47 +714,47 @@ msgstr "" msgid "Completed build output" msgstr "" -#: build/models.py:1118 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1143 +#: build/models.py:1157 msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1147 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1151 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1158 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1162 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1166 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1206 stock/templates/stock/item_base.html:306 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1207 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1214 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 @@ -765,19 +766,19 @@ msgstr "" msgid "Stock Item" msgstr "" -#: build/models.py:1215 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1228 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1236 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1237 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" @@ -801,7 +802,7 @@ msgstr "" msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:26 build/views.py:308 build/views.py:794 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" msgstr "" @@ -811,7 +812,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:794 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -954,7 +955,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 @@ -1139,7 +1140,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:667 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1226,141 +1227,145 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:173 stock/models.py:969 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:182 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:248 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:269 build/views.py:359 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:270 build/views.py:360 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:282 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:284 build/views.py:485 +#: build/views.py:295 build/views.py:496 msgid "Build output must be specified" msgstr "" -#: build/views.py:296 +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:394 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:400 +#: build/views.py:411 msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:411 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:427 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:469 +#: build/views.py:480 msgid "Invalid stock status value selected" msgstr "" -#: build/views.py:476 +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:581 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:721 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:742 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:775 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:784 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:799 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:811 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:854 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:860 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:861 templates/js/bom.js:230 templates/js/build.js:575 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:863 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1026 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1030 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1059 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1072 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1108 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1118 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1128 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1133 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1766,7 +1771,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:26 #: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:171 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" @@ -1865,7 +1870,7 @@ msgstr "" msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1372 +#: company/models.py:312 company/models.py:463 order/views.py:1384 msgid "Select part" msgstr "" @@ -1905,7 +1910,7 @@ msgstr "" #: company/models.py:475 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:176 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" @@ -2017,7 +2022,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,35 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/it/LC_MESSAGES/django.mo b/InvenTree/locale/it/LC_MESSAGES/django.mo index 71cbdf3e9d8d54be31066ec4ad8628bc2c1f2845..900921d249eb26795e2913500959daa683a1746e 100644 GIT binary patch delta 91 zcmeyvbew5|3M21CRgH-;TAoG*MuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= mK#{!k(!}&s-H_D8Tq_07lEj?M#5}mLl|p7oyl2S7uk8Te^c|7_ delta 161 zcmX@k^oMDJ3Zv6RRSo_CM`v$GcUOfl*Pvief4_;oTJ@2xjzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3OJ$+qu!%~ZiGxPJT6bvU`C\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,35 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/ja/LC_MESSAGES/django.mo b/InvenTree/locale/ja/LC_MESSAGES/django.mo index 314bedb17d5caa2d590b5786ba725a4f8d4dab37..c8fe740f6ac643152691b6a731fd9ff34fc513db 100644 GIT binary patch delta 92 zcmey$bdYI+3M2bORgH-;T3$v5MuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= nK#{!k(!}&s-H_D8Tq^~y#Dc`U)Z$dQxRpXyV!T(t#IFqi_U#?X delta 145 zcmX@e^p$CX3ZwNzRSo_CM`v$GcUOfl*Pvief4_;oTKSQ#jzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3O\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,34 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/pl/LC_MESSAGES/django.mo b/InvenTree/locale/pl/LC_MESSAGES/django.mo index 16fcd00009b4b2229c050ee6bcb41074b1b3e6a5..89d5c273e3d431e7842a317bfebddcdbe6cfb0ff 100644 GIT binary patch delta 91 zcmeBUxxqX^g>l|QRgH-;S{_CQMuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= mK#{!k(!}&s-H_D8Tq}iu{G80<47jM3LP1V^fX~LSl8gZF{T(I% delta 162 zcmcb?+{ZFOh4IQnRSo_CM`v$GcUOfl*Pvief4_;oTJ@2xjzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3OJ$+qu!%~ZiGxPJT6bv_>=VSx` Dk6tlh diff --git a/InvenTree/locale/pl/LC_MESSAGES/django.po b/InvenTree/locale/pl/LC_MESSAGES/django.po index 8f82a13ba3..edc3b32d2b 100644 --- a/InvenTree/locale/pl/LC_MESSAGES/django.po +++ b/InvenTree/locale/pl/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-21 09:17+0000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: 2021-04-21 09:33\n" "Last-Translator: \n" "Language-Team: Polish\n" @@ -67,35 +67,36 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:375 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:378 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:399 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:403 InvenTree/helpers.py:406 InvenTree/helpers.py:409 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:414 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:422 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:426 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" @@ -140,7 +141,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 @@ -165,23 +166,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:496 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:497 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" @@ -375,16 +376,16 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1227 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 #: build/templates/build/detail.html:31 common/models.py:703 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:200 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 @@ -458,7 +459,7 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:445 +#: build/templates/build/detail.html:59 order/models.py:455 #: order/templates/order/receive_parts.html:24 #: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 @@ -508,7 +509,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -516,8 +517,8 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:195 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 #: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 @@ -540,10 +541,10 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:669 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 #: part/models.py:1876 part/models.py:1888 part/models.py:1906 @@ -628,7 +629,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" @@ -678,9 +679,9 @@ msgstr "" #: company/models.py:135 company/models.py:501 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:234 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 @@ -713,47 +714,47 @@ msgstr "" msgid "Completed build output" msgstr "" -#: build/models.py:1118 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1143 +#: build/models.py:1157 msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1147 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1151 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1158 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1162 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1166 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1206 stock/templates/stock/item_base.html:306 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1207 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1214 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 @@ -765,19 +766,19 @@ msgstr "" msgid "Stock Item" msgstr "" -#: build/models.py:1215 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1228 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1236 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1237 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" @@ -801,7 +802,7 @@ msgstr "" msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:26 build/views.py:308 build/views.py:794 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" msgstr "" @@ -811,7 +812,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:794 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -954,7 +955,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 @@ -1139,7 +1140,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:667 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1226,141 +1227,145 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:173 stock/models.py:969 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:182 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:248 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:269 build/views.py:359 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:270 build/views.py:360 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:282 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:284 build/views.py:485 +#: build/views.py:295 build/views.py:496 msgid "Build output must be specified" msgstr "" -#: build/views.py:296 +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:394 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:400 +#: build/views.py:411 msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:411 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:427 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:469 +#: build/views.py:480 msgid "Invalid stock status value selected" msgstr "" -#: build/views.py:476 +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:581 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:721 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:742 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:775 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:784 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:799 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:811 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:854 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:860 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:861 templates/js/bom.js:230 templates/js/build.js:575 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:863 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1026 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1030 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1059 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1072 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1108 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1118 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1128 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1133 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1766,7 +1771,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:26 #: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:171 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" @@ -1865,7 +1870,7 @@ msgstr "" msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1372 +#: company/models.py:312 company/models.py:463 order/views.py:1384 msgid "Select part" msgstr "" @@ -1905,7 +1910,7 @@ msgstr "" #: company/models.py:475 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:176 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" @@ -2017,7 +2022,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,34 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/ru/LC_MESSAGES/django.mo b/InvenTree/locale/ru/LC_MESSAGES/django.mo index 7007a3d4e50ddf1c5e7d2870e6247ecea1df5a7b..45a221f8727b8cb60022d5cd21b59c05fc4a8351 100644 GIT binary patch delta 251 zcmZo;dBZ$Gg>lnFRgH-;TAoG*MuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= zK#{!k(!}&s-H_D8Tq}j3(&FOG#5}mLl|oTzd{F4bueFm48AauZ6s#09H1bpp z4HWEb6^sV54AYq)<}>mI5kNFf`EwX*NV?wzUNs1ylhy$`r{c fOQ33)9M~R1L!hiQ)HoYkn0ZD(^Nck$t+^Ng6{7QP{P45s4NjiL{gaqTn9C#$~ zs;u&ThJvF*Ezvxy>P1;lAkEimTl5HKj6lB+R^l^82#f#&?QYJzKg(xBD+gW7Cmw7z ry9y^mx2=%h3S-z>U5>Mxef`$`|6^`vTH5K3##+P(yq0k7-Z=+9*YHry diff --git a/InvenTree/locale/ru/LC_MESSAGES/django.po b/InvenTree/locale/ru/LC_MESSAGES/django.po index e77638edc6..d14c214d50 100644 --- a/InvenTree/locale/ru/LC_MESSAGES/django.po +++ b/InvenTree/locale/ru/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-21 09:17+0000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: 2021-04-21 09:33\n" "Last-Translator: \n" "Language-Team: Russian\n" @@ -67,35 +67,36 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:375 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:378 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:399 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:403 InvenTree/helpers.py:406 InvenTree/helpers.py:409 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:414 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:422 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:426 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" @@ -140,7 +141,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 @@ -165,23 +166,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:496 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:497 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" @@ -375,16 +376,16 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1227 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 #: build/templates/build/detail.html:31 common/models.py:703 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:200 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 @@ -458,7 +459,7 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:445 +#: build/templates/build/detail.html:59 order/models.py:455 #: order/templates/order/receive_parts.html:24 #: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 @@ -508,7 +509,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -516,8 +517,8 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:195 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 #: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 @@ -540,10 +541,10 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:669 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 #: part/models.py:1876 part/models.py:1888 part/models.py:1906 @@ -628,7 +629,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" @@ -678,9 +679,9 @@ msgstr "" #: company/models.py:135 company/models.py:501 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:234 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 @@ -713,47 +714,47 @@ msgstr "" msgid "Completed build output" msgstr "" -#: build/models.py:1118 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1143 +#: build/models.py:1157 msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1147 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1151 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1158 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1162 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1166 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1206 stock/templates/stock/item_base.html:306 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1207 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1214 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 @@ -765,19 +766,19 @@ msgstr "" msgid "Stock Item" msgstr "" -#: build/models.py:1215 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1228 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1236 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1237 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" @@ -801,7 +802,7 @@ msgstr "" msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:26 build/views.py:308 build/views.py:794 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" msgstr "" @@ -811,7 +812,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:794 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -954,7 +955,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 @@ -1139,7 +1140,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:667 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1226,141 +1227,145 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:173 stock/models.py:969 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:182 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:248 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:269 build/views.py:359 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:270 build/views.py:360 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:282 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:284 build/views.py:485 +#: build/views.py:295 build/views.py:496 msgid "Build output must be specified" msgstr "" -#: build/views.py:296 +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:394 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:400 +#: build/views.py:411 msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:411 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:427 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:469 +#: build/views.py:480 msgid "Invalid stock status value selected" msgstr "" -#: build/views.py:476 +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:581 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:721 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:742 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:775 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:784 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:799 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:811 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:854 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:860 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:861 templates/js/bom.js:230 templates/js/build.js:575 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:863 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1026 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1030 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1059 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1072 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1108 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1118 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1128 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1133 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1766,7 +1771,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:26 #: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:171 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" @@ -1865,7 +1870,7 @@ msgstr "" msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1372 +#: company/models.py:312 company/models.py:463 order/views.py:1384 msgid "Select part" msgstr "" @@ -1905,7 +1910,7 @@ msgstr "" #: company/models.py:475 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:176 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" @@ -2017,7 +2022,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,34 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/tr/LC_MESSAGES/django.po b/InvenTree/locale/tr/LC_MESSAGES/django.po index b8105d1fde..db257af1fe 100644 --- a/InvenTree/locale/tr/LC_MESSAGES/django.po +++ b/InvenTree/locale/tr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-21 22:29+1000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -73,35 +73,36 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:375 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:378 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:399 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:403 InvenTree/helpers.py:406 InvenTree/helpers.py:409 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:414 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:422 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:426 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" @@ -146,7 +147,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 @@ -171,23 +172,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:496 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:497 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" @@ -378,20 +379,19 @@ msgid "Target Date" msgstr "" #: build/forms.py:43 build/models.py:224 -msgid "" -"Target date for build completion. Build will be overdue after this date." +msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1227 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 #: build/templates/build/detail.html:31 common/models.py:703 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:200 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 @@ -465,7 +465,7 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:445 +#: build/templates/build/detail.html:59 order/models.py:455 #: order/templates/order/receive_parts.html:24 #: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 @@ -515,7 +515,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -523,8 +523,8 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:195 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 #: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 @@ -547,10 +547,10 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:669 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 #: part/models.py:1876 part/models.py:1888 part/models.py:1906 @@ -587,9 +587,7 @@ msgid "Source Location" msgstr "" #: build/models.py:178 -msgid "" -"Select location to take stock from for this build (leave blank to take from " -"any stock location)" +msgid "Select location to take stock from for this build (leave blank to take from any stock location)" msgstr "" #: build/models.py:183 @@ -637,7 +635,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" @@ -687,9 +685,9 @@ msgstr "" #: company/models.py:135 company/models.py:501 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:234 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 @@ -722,48 +720,47 @@ msgstr "" msgid "Completed build output" msgstr "" -#: build/models.py:1118 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1143 -msgid "" -"Build item must specify a build output, as master part is marked as trackable" +#: build/models.py:1157 +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1147 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1151 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1158 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1162 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1166 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1206 stock/templates/stock/item_base.html:306 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1207 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1214 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 @@ -775,19 +772,19 @@ msgstr "" msgid "Stock Item" msgstr "" -#: build/models.py:1215 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1228 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1236 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1237 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" @@ -811,7 +808,7 @@ msgstr "" msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:26 build/views.py:308 build/views.py:794 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" msgstr "" @@ -821,7 +818,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:794 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -862,8 +859,7 @@ msgid "Automatically Allocate Stock" msgstr "" #: build/templates/build/auto_allocate.html:10 -msgid "" -"The following stock items will be allocated to the specified build output" +msgid "The following stock items will be allocated to the specified build output" msgstr "" #: build/templates/build/auto_allocate.html:37 @@ -965,7 +961,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 @@ -1089,9 +1085,7 @@ msgstr "" #: build/templates/build/create_build_item.html:11 #, python-format -msgid "" -"The allocated stock will be installed into the following build output:
" -"%(output)s" +msgid "The allocated stock will be installed into the following build output:
%(output)s" msgstr "" #: build/templates/build/create_build_item.html:17 @@ -1152,7 +1146,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:667 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1239,141 +1233,145 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:173 stock/models.py:969 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:182 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:248 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:269 build/views.py:359 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:270 build/views.py:360 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:282 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:284 build/views.py:485 +#: build/views.py:295 build/views.py:496 msgid "Build output must be specified" msgstr "" -#: build/views.py:296 +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:394 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:400 +#: build/views.py:411 msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:411 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:427 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:469 +#: build/views.py:480 msgid "Invalid stock status value selected" msgstr "" -#: build/views.py:476 +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:581 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:721 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:742 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:775 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:784 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:799 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:811 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:854 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:860 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:861 templates/js/bom.js:230 templates/js/build.js:575 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:863 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1026 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1030 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1059 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1072 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1108 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1118 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1128 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1133 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1779,7 +1777,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:26 #: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:171 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" @@ -1878,7 +1876,7 @@ msgstr "" msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1372 +#: company/models.py:312 company/models.py:463 order/views.py:1384 msgid "Select part" msgstr "" @@ -1918,7 +1916,7 @@ msgstr "" #: company/models.py:475 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:176 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" @@ -2032,8 +2030,7 @@ msgstr "" #, python-format msgid "" "There are %(count)s parts sourced from this company.
\n" -"If this supplier is deleted, these supplier part entries will also be " -"deleted." +"If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" #: company/templates/company/detail.html:21 @@ -2048,7 +2045,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2137,13 +2134,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2197,9 +2194,7 @@ msgstr "" #: company/templates/company/manufacturer_part_delete.html:36 #, python-format -msgid "" -"There are %(count)s suppliers defined for this manufacturer part. If you " -"delete it, the following supplier parts will also be deleted:" +msgid "There are %(count)s suppliers defined for this manufacturer part. If you delete it, the following supplier parts will also be deleted:" msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 @@ -2243,7 +2238,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2269,7 +2264,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2283,7 +2278,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2295,7 +2290,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2374,7 +2369,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2484,15 +2479,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2582,9 +2577,8 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 -msgid "" -"Target date for order completion. Order will be overdue after this date." +#: order/forms.py:145 order/models.py:462 +msgid "Target date for order completion. Order will be overdue after this date." msgstr "" #: order/forms.py:235 @@ -2619,7 +2613,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2653,16 +2647,15 @@ msgid "Target Delivery Date" msgstr "" #: order/models.py:213 -msgid "" -"Expected date for order delivery. Order will be overdue after this date." +msgid "Expected date for order delivery. Order will be overdue after this date." msgstr "" #: order/models.py:219 msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2670,120 +2663,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2831,9 +2832,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2845,12 +2859,11 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 -msgid "" -"After placing this purchase order, line items will no longer be editable." +#: order/templates/order/order_issue.html:8 +msgid "After placing this purchase order, line items will no longer be editable." msgstr "" #: order/templates/order/order_notes.html:13 @@ -2929,43 +2942,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2988,7 +2987,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3041,6 +3040,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3103,9 +3106,7 @@ msgid "Sales Order Notes" msgstr "" #: order/templates/order/sales_order_ship.html:10 -msgid "" -"This order has not been fully allocated. If the order is marked as shipped, " -"it can no longer be adjusted." +msgid "This order has not been fully allocated. If the order is marked as shipped, it can no longer be adjusted." msgstr "" #: order/templates/order/sales_order_ship.html:12 @@ -3237,65 +3238,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3481,7 +3482,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3826,9 +3827,7 @@ msgid "Select Related Part" msgstr "" #: part/models.py:2440 -msgid "" -"Error creating relationship: check that the part is not related to itself " -"and that the relationship is unique" +msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" #: part/templates/part/allocation.html:11 @@ -3859,8 +3858,7 @@ msgstr "" #: part/templates/part/bom.html:21 #, python-format -msgid "" -"The BOM for %(part)s was last checked by %(checker)s on %(check_date)s" +msgid "The BOM for %(part)s was last checked by %(checker)s on %(check_date)s" msgstr "" #: part/templates/part/bom.html:25 @@ -3995,8 +3993,7 @@ msgid "Requirements for BOM upload" msgstr "" #: part/templates/part/bom_upload/upload_file.html:21 -msgid "" -"The BOM file must contain the required named columns as provided in the " +msgid "The BOM file must contain the required named columns as provided in the " msgstr "" #: part/templates/part/bom_upload/upload_file.html:21 @@ -4013,8 +4010,7 @@ msgstr "" #: part/templates/part/bom_validate.html:6 #, python-format -msgid "" -"Confirm that the Bill of Materials (BOM) is valid for:
%(part)s" +msgid "Confirm that the Bill of Materials (BOM) is valid for:
%(part)s" msgstr "" #: part/templates/part/bom_validate.html:9 @@ -4033,7 +4029,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4115,8 +4111,7 @@ msgid "This category contains %(count)s child categories" msgstr "" #: part/templates/part/category_delete.html:9 -msgid "" -"If this category is deleted, these child categories will be moved to the" +msgid "If this category is deleted, these child categories will be moved to the" msgstr "" #: part/templates/part/category_delete.html:11 @@ -4134,15 +4129,11 @@ msgstr "" #: part/templates/part/category_delete.html:27 #, python-format -msgid "" -"If this category is deleted, these parts will be moved to the parent " -"category %(path)s" +msgid "If this category is deleted, these parts will be moved to the parent category %(path)s" msgstr "" #: part/templates/part/category_delete.html:29 -msgid "" -"If this category is deleted, these parts will be moved to the top-level " -"category Teile" +msgid "If this category is deleted, these parts will be moved to the top-level category Teile" msgstr "" #: part/templates/part/category_navbar.html:34 @@ -4489,37 +4480,27 @@ msgstr "" #: part/templates/part/partial_delete.html:12 #, python-format -msgid "" -"This part is used in BOMs for %(count)s other parts. If you delete this " -"part, the BOMs for the following parts will be updated" +msgid "This part is used in BOMs for %(count)s other parts. If you delete this part, the BOMs for the following parts will be updated" msgstr "" #: part/templates/part/partial_delete.html:22 #, python-format -msgid "" -"There are %(count)s stock entries defined for this part. If you delete this " -"part, the following stock entries will also be deleted:" +msgid "There are %(count)s stock entries defined for this part. If you delete this part, the following stock entries will also be deleted:" msgstr "" #: part/templates/part/partial_delete.html:33 #, python-format -msgid "" -"There are %(count)s manufacturers defined for this part. If you delete this " -"part, the following manufacturer parts will also be deleted:" +msgid "There are %(count)s manufacturers defined for this part. If you delete this part, the following manufacturer parts will also be deleted:" msgstr "" #: part/templates/part/partial_delete.html:44 #, python-format -msgid "" -"There are %(count)s suppliers defined for this part. If you delete this " -"part, the following supplier parts will also be deleted:" +msgid "There are %(count)s suppliers defined for this part. If you delete this part, the following supplier parts will also be deleted:" msgstr "" #: part/templates/part/partial_delete.html:55 #, python-format -msgid "" -"There are %(count)s unique parts tracked for '%(full_name)s'. Deleting this " -"part will permanently remove this tracking information." +msgid "There are %(count)s unique parts tracked for '%(full_name)s'. Deleting this part will permanently remove this tracking information." msgstr "" #: part/templates/part/related.html:18 @@ -4738,63 +4719,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -4942,9 +4923,7 @@ msgid "Enter unique serial numbers (or leave blank)" msgstr "" #: stock/forms.py:169 -msgid "" -"Destination for serialized stock (by default, will remain in current " -"location)" +msgid "Destination for serialized stock (by default, will remain in current location)" msgstr "" #: stock/forms.py:171 @@ -5126,8 +5105,7 @@ msgid "Destination Sales Order" msgstr "" #: stock/models.py:476 -msgid "" -"Expiry date for stock item. Stock will be considered expired after this date" +msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" #: stock/models.py:489 @@ -5274,9 +5252,7 @@ msgid "Stock Item Attachments" msgstr "" #: stock/templates/stock/item_base.html:24 -msgid "" -"You are not in the list of owners of this item. This stock item cannot be " -"edited." +msgid "You are not in the list of owners of this item. This stock item cannot be edited." msgstr "" #: stock/templates/stock/item_base.html:31 @@ -5293,8 +5269,7 @@ msgstr "" #: stock/templates/stock/item_base.html:53 #, python-format -msgid "" -"This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" msgstr "" #: stock/templates/stock/item_base.html:61 @@ -5303,9 +5278,7 @@ msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" msgstr "" #: stock/templates/stock/item_base.html:67 -msgid "" -"This stock item is serialized - it has a unique serial number and the " -"quantity cannot be adjusted." +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." msgstr "" #: stock/templates/stock/item_base.html:71 @@ -5313,8 +5286,7 @@ msgid "This stock item cannot be deleted as it has child items" msgstr "" #: stock/templates/stock/item_base.html:75 -msgid "" -"This stock item will be automatically deleted when all stock is depleted." +msgid "This stock item will be automatically deleted when all stock is depleted." msgstr "" #: stock/templates/stock/item_base.html:95 @@ -5354,15 +5326,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5463,8 +5435,7 @@ msgstr "" #: stock/templates/stock/item_delete.html:12 #, python-format -msgid "" -"This will remove %(qty)s units of %(full_name)s from stock." +msgid "This will remove %(qty)s units of %(full_name)s from stock." msgstr "" #: stock/templates/stock/item_install.html:7 @@ -5510,9 +5481,7 @@ msgid "Add Test Data" msgstr "" #: stock/templates/stock/location.html:20 -msgid "" -"You are not in the list of owners of this location. This stock location " -"cannot be edited." +msgid "You are not in the list of owners of this location. This stock location cannot be edited." msgstr "" #: stock/templates/stock/location.html:37 @@ -5559,7 +5528,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5745,7 +5714,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5923,6 +5892,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -6006,7 +6000,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -6020,7 +6014,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -6039,24 +6033,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "" -"\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected " -"color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6119,13 +6095,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6203,8 +6189,7 @@ msgid "Link Barcode to Stock Item" msgstr "" #: templates/js/barcode.js:311 -msgid "" -"This will remove the association between this stock item and the barcode" +msgid "This will remove the association between this stock item and the barcode" msgstr "" #: templates/js/barcode.js:317 @@ -6322,7 +6307,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6455,11 +6440,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -7033,6 +7013,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -7045,7 +7029,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7106,21 +7090,15 @@ msgid "Change password" msgstr "" #: templates/registration/password_reset_confirm.html:61 -msgid "" -"The password reset link was invalid, possibly because it has already been " -"used. Please request a new password reset." +msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." msgstr "" #: templates/registration/password_reset_done.html:52 -msgid "" -"We've emailed you instructions for setting your password, if an account " -"exists with the email you entered. You should receive them shortly." +msgid "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." msgstr "" #: templates/registration/password_reset_done.html:55 -msgid "" -"If you don't receive an email, please make sure you've entered the address " -"you registered with, and check your spam folder." +msgid "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." msgstr "" #: templates/registration/password_reset_form.html:53 @@ -7183,43 +7161,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7255,34 +7233,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/zh/LC_MESSAGES/django.mo b/InvenTree/locale/zh/LC_MESSAGES/django.mo index 6c5906d1cd061dff54de8b533942893de34efc9e..d02b517fab4f5decbc17e3e4aaf12a440530d8f6 100644 GIT binary patch delta 140 zcmcb}bed^`3ZvjeRgH-;S|LUTMuxfuCb~w33I>)|#>QMeiNz(lAw`LK#W{&3`9)R= zK#{!k(!}&s-H_D8Tq_0VjLf{$;#7s;%-n*U%(TqZ6u1g2g{q8rXTOPGqg4ZPN{bS6 cblvica*M4L@(RG*Vp~IN1qjpDz?zEz04qf<2><{9 delta 163 zcmX@jbdhO-3ZwW$RSo_CM`v$GcUOfl*Pvief4_;oTJ@2xjzPM<{<%0zOD*3uD*_*J`Rp9E8ZLQsfoE(3OJ$+qu!%~ZiGxPJT6bvWc_GV-N E0Bz$j1poj5 diff --git a/InvenTree/locale/zh/LC_MESSAGES/django.po b/InvenTree/locale/zh/LC_MESSAGES/django.po index 2534d27c42..2075ec9326 100644 --- a/InvenTree/locale/zh/LC_MESSAGES/django.po +++ b/InvenTree/locale/zh/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-21 09:17+0000\n" +"POT-Creation-Date: 2021-05-05 17:33+1000\n" "PO-Revision-Date: 2021-04-21 09:33\n" "Last-Translator: \n" "Language-Team: Chinese Simplified\n" @@ -67,35 +67,36 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:375 order/models.py:245 order/models.py:344 -#: stock/views.py:1763 -msgid "Invalid quantity provided" -msgstr "" - -#: InvenTree/helpers.py:378 -msgid "Empty serial number string" -msgstr "" - -#: InvenTree/helpers.py:399 +#: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:403 InvenTree/helpers.py:406 InvenTree/helpers.py:409 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 +#: stock/views.py:1763 +msgid "Invalid quantity provided" +msgstr "" + +#: InvenTree/helpers.py:387 +msgid "Empty serial number string" +msgstr "" + +#: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 +#: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" msgstr "" -#: InvenTree/helpers.py:414 +#: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" msgstr "" -#: InvenTree/helpers.py:422 +#: InvenTree/helpers.py:453 msgid "No serial numbers found" msgstr "" -#: InvenTree/helpers.py:426 +#: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" @@ -140,7 +141,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 #: company/templates/company/supplier_part_detail.html:31 label/models.py:108 -#: order/models.py:101 order/templates/order/purchase_order_detail.html:168 +#: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 #: report/models.py:505 report/models.py:544 @@ -165,23 +166,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:491 msgid "English" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:492 msgid "French" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:493 msgid "German" msgstr "" -#: InvenTree/settings.py:496 +#: InvenTree/settings.py:494 msgid "Polish" msgstr "" -#: InvenTree/settings.py:497 +#: InvenTree/settings.py:495 msgid "Turkish" msgstr "" @@ -375,16 +376,16 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1227 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 #: build/templates/build/detail.html:31 common/models.py:703 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:593 order/models.py:784 +#: order/forms.py:278 order/models.py:603 order/models.py:794 #: order/templates/order/order_wizard/select_parts.html:32 -#: order/templates/order/purchase_order_detail.html:200 +#: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:159 @@ -458,7 +459,7 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:445 +#: build/templates/build/detail.html:59 order/models.py:455 #: order/templates/order/receive_parts.html:24 #: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 @@ -508,7 +509,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:41 +#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" msgstr "" @@ -516,8 +517,8 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:595 -#: order/templates/order/purchase_order_detail.html:195 +#: build/models.py:127 order/models.py:99 order/models.py:605 +#: order/templates/order/purchase_order_detail.html:170 #: order/templates/order/sales_order_detail.html:219 part/models.py:2187 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 @@ -540,10 +541,10 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:669 -#: order/models.py:637 order/models.py:669 +#: build/templates/build/detail.html:26 company/models.py:688 +#: order/models.py:647 order/models.py:679 #: order/templates/order/order_wizard/select_parts.html:30 -#: order/templates/order/purchase_order_detail.html:156 +#: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:207 part/models.py:321 #: part/models.py:1876 part/models.py:1888 part/models.py:1906 @@ -628,7 +629,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:451 +#: build/models.py:223 order/models.py:461 msgid "Target completion date" msgstr "" @@ -678,9 +679,9 @@ msgstr "" #: company/models.py:135 company/models.py:501 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:597 order/templates/order/po_navbar.html:29 +#: order/models.py:607 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 -#: order/templates/order/purchase_order_detail.html:234 +#: order/templates/order/purchase_order_detail.html:209 #: order/templates/order/sales_order_detail.html:264 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 @@ -713,47 +714,47 @@ msgstr "" msgid "Completed build output" msgstr "" -#: build/models.py:1118 +#: build/models.py:1132 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1143 +#: build/models.py:1157 msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" -#: build/models.py:1147 +#: build/models.py:1161 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:1151 +#: build/models.py:1165 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1158 order/models.py:758 +#: build/models.py:1172 order/models.py:768 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1162 order/models.py:761 +#: build/models.py:1176 order/models.py:771 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1166 +#: build/models.py:1180 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1206 stock/templates/stock/item_base.html:306 +#: build/models.py:1220 stock/templates/stock/item_base.html:306 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1207 +#: build/models.py:1221 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1214 part/templates/part/allocation.html:18 +#: build/models.py:1228 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 @@ -765,19 +766,19 @@ msgstr "" msgid "Stock Item" msgstr "" -#: build/models.py:1215 +#: build/models.py:1229 msgid "Source stock item" msgstr "" -#: build/models.py:1228 +#: build/models.py:1242 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1236 +#: build/models.py:1250 msgid "Install into" msgstr "" -#: build/models.py:1237 +#: build/models.py:1251 msgid "Destination stock item" msgstr "" @@ -801,7 +802,7 @@ msgstr "" msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:26 build/views.py:308 build/views.py:794 +#: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" msgstr "" @@ -811,7 +812,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:794 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -954,7 +955,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:667 +#: build/templates/build/detail.html:84 order/models.py:677 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 @@ -1139,7 +1140,7 @@ msgstr "" msgid "Alter the quantity of stock allocated to the build output" msgstr "" -#: build/templates/build/index.html:28 build/views.py:667 +#: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" msgstr "" @@ -1226,141 +1227,145 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:173 stock/models.py:969 stock/views.py:1789 +#: build/views.py:168 +msgid "Maximum output quantity is " +msgstr "" + +#: build/views.py:184 stock/models.py:969 stock/views.py:1789 msgid "Serial numbers already exist" msgstr "" -#: build/views.py:182 +#: build/views.py:193 msgid "Serial numbers required for trackable build output" msgstr "" -#: build/views.py:248 +#: build/views.py:259 msgid "Delete Build Output" msgstr "" -#: build/views.py:269 build/views.py:359 +#: build/views.py:280 build/views.py:370 msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:270 build/views.py:360 stock/views.py:425 +#: build/views.py:281 build/views.py:371 stock/views.py:425 msgid "Check the confirmation box" msgstr "" -#: build/views.py:282 +#: build/views.py:293 msgid "Build output does not match build" msgstr "" -#: build/views.py:284 build/views.py:485 +#: build/views.py:295 build/views.py:496 msgid "Build output must be specified" msgstr "" -#: build/views.py:296 +#: build/views.py:307 msgid "Build output deleted" msgstr "" -#: build/views.py:394 +#: build/views.py:405 msgid "Complete Build Order" msgstr "" -#: build/views.py:400 +#: build/views.py:411 msgid "Build order cannot be completed - incomplete outputs remain" msgstr "" -#: build/views.py:411 +#: build/views.py:422 msgid "Completed build order" msgstr "" -#: build/views.py:427 +#: build/views.py:438 msgid "Complete Build Output" msgstr "" -#: build/views.py:469 +#: build/views.py:480 msgid "Invalid stock status value selected" msgstr "" -#: build/views.py:476 +#: build/views.py:487 msgid "Quantity to complete cannot exceed build output quantity" msgstr "" -#: build/views.py:482 +#: build/views.py:493 msgid "Confirm completion of incomplete build" msgstr "" -#: build/views.py:581 +#: build/views.py:592 msgid "Build output completed" msgstr "" -#: build/views.py:721 +#: build/views.py:732 msgid "Created new build" msgstr "" -#: build/views.py:742 +#: build/views.py:753 msgid "Edit Build Order Details" msgstr "" -#: build/views.py:775 +#: build/views.py:786 msgid "Edited build" msgstr "" -#: build/views.py:784 +#: build/views.py:795 msgid "Delete Build Order" msgstr "" -#: build/views.py:799 +#: build/views.py:810 msgid "Removed parts from build allocation" msgstr "" -#: build/views.py:811 +#: build/views.py:822 msgid "Allocate stock to build output" msgstr "" -#: build/views.py:854 +#: build/views.py:865 msgid "Item must be currently in stock" msgstr "" -#: build/views.py:860 +#: build/views.py:871 msgid "Stock item is over-allocated" msgstr "" -#: build/views.py:861 templates/js/bom.js:230 templates/js/build.js:575 +#: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" msgstr "" -#: build/views.py:863 +#: build/views.py:874 msgid "Stock item must be selected" msgstr "" -#: build/views.py:1026 +#: build/views.py:1037 msgid "Edit Stock Allocation" msgstr "" -#: build/views.py:1030 +#: build/views.py:1041 msgid "Updated Build Item" msgstr "" -#: build/views.py:1059 +#: build/views.py:1070 msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1072 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1108 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:189 order/views.py:210 msgid "Edit Attachment" msgstr "" -#: build/views.py:1118 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:193 order/views.py:214 msgid "Attachment updated" msgstr "" -#: build/views.py:1128 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:229 order/views.py:243 msgid "Delete Attachment" msgstr "" -#: build/views.py:1133 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 msgid "Deleted attachment" msgstr "" @@ -1766,7 +1771,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:26 #: company/templates/company/supplier_part_base.html:101 #: company/templates/company/supplier_part_detail.html:35 -#: order/templates/order/purchase_order_detail.html:183 part/bom.py:171 +#: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" @@ -1865,7 +1870,7 @@ msgstr "" msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1372 +#: company/models.py:312 company/models.py:463 order/views.py:1384 msgid "Select part" msgstr "" @@ -1905,7 +1910,7 @@ msgstr "" #: company/models.py:475 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 -#: order/templates/order/purchase_order_detail.html:174 part/bom.py:176 +#: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" @@ -2017,7 +2022,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
\n" +msgid "" +"There are %(count)s parts sourced from this company.
\n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2033,7 +2039,7 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:440 +#: company/templates/company/detail.html:67 order/models.py:450 #: order/templates/order/sales_order_base.html:92 stock/models.py:415 #: stock/models.py:416 stock/templates/stock/item_base.html:251 #: templates/js/company.js:40 templates/js/order.js:267 @@ -2122,13 +2128,13 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 -#: order/templates/order/purchase_order_detail.html:75 +#: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 -#: order/templates/order/purchase_order_detail.html:74 +#: order/templates/order/purchase_order_detail.html:49 #: part/templates/part/supplier.html:17 templates/js/stock.js:1163 msgid "New Supplier Part" msgstr "" @@ -2226,7 +2232,7 @@ msgstr "" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/manufacturer.html:24 part/templates/part/params.html:44 #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 -#: stock/views.py:1002 users/models.py:184 +#: stock/views.py:1002 users/models.py:187 msgid "Delete" msgstr "" @@ -2252,7 +2258,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:40 +#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2266,7 +2272,7 @@ msgstr "" #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 #: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 -#: users/models.py:43 +#: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2278,7 +2284,7 @@ msgstr "" #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 #: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 -#: users/models.py:42 +#: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2357,7 +2363,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2624 +#: part/templates/part/sale_prices.html:17 part/views.py:2636 msgid "Add Price Break" msgstr "" @@ -2467,15 +2473,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2628 +#: company/views.py:799 part/views.py:2640 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2672 +#: company/views.py:855 part/views.py:2684 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2686 +#: company/views.py:870 part/views.py:2698 msgid "Delete Price Break" msgstr "" @@ -2565,7 +2571,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:452 +#: order/forms.py:145 order/models.py:462 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2601,7 +2607,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:445 +#: order/models.py:182 order/models.py:455 msgid "Purchase order status" msgstr "" @@ -2642,8 +2648,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 order/models.py:342 part/views.py:1586 -#: stock/models.py:270 stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:270 +#: stock/models.py:953 msgid "Quantity must be greater than zero" msgstr "" @@ -2651,120 +2657,128 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:337 +#: order/models.py:344 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:359 +#: order/models.py:348 +msgid "Quantity must be an integer" +msgstr "" + +#: order/models.py:350 +msgid "Quantity must be a positive number" +msgstr "" + +#: order/models.py:369 msgid "Received items" msgstr "" -#: order/models.py:441 +#: order/models.py:451 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer Reference " msgstr "" -#: order/models.py:447 +#: order/models.py:457 msgid "Customer order reference code" msgstr "" -#: order/models.py:455 templates/js/order.js:303 +#: order/models.py:465 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:462 +#: order/models.py:472 msgid "shipped by" msgstr "" -#: order/models.py:506 +#: order/models.py:516 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:593 +#: order/models.py:603 msgid "Item quantity" msgstr "" -#: order/models.py:595 +#: order/models.py:605 msgid "Line item reference" msgstr "" -#: order/models.py:597 +#: order/models.py:607 msgid "Line item notes" msgstr "" -#: order/models.py:623 order/models.py:667 +#: order/models.py:633 order/models.py:677 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:624 order/templates/order/order_base.html:9 +#: order/models.py:634 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 #: stock/templates/stock/item_base.html:313 templates/js/order.js:148 msgid "Purchase Order" msgstr "" -#: order/models.py:638 +#: order/models.py:648 msgid "Supplier part" msgstr "" -#: order/models.py:641 order/templates/order/order_base.html:131 -#: order/templates/order/purchase_order_detail.html:214 +#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:641 +#: order/models.py:651 msgid "Number of items received" msgstr "" -#: order/models.py:648 stock/models.py:508 +#: order/models.py:658 stock/models.py:508 #: stock/templates/stock/item_base.html:320 msgid "Purchase Price" msgstr "" -#: order/models.py:649 +#: order/models.py:659 msgid "Unit purchase price" msgstr "" -#: order/models.py:743 order/models.py:745 +#: order/models.py:753 order/models.py:755 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:749 +#: order/models.py:759 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:751 +#: order/models.py:761 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:754 +#: order/models.py:764 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:764 +#: order/models.py:774 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:769 +#: order/models.py:779 msgid "Line" msgstr "" -#: order/models.py:780 +#: order/models.py:790 msgid "Item" msgstr "" -#: order/models.py:781 +#: order/models.py:791 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:784 +#: order/models.py:794 msgid "Enter stock allocation quantity" msgstr "" @@ -2812,9 +2826,22 @@ msgstr "" msgid "Issued" msgstr "" -#: order/templates/order/order_cancel.html:7 -#: order/templates/order/sales_order_cancel.html:9 -msgid "Cancelling this order means that the order will no longer be editable." +#: order/templates/order/order_base.html:180 +#: order/templates/order/purchase_order_detail.html:100 +#: part/templates/part/category.html:185 part/templates/part/category.html:227 +#: stock/templates/stock/location.html:191 templates/js/stock.js:708 +#: templates/js/stock.js:1169 +msgid "New Location" +msgstr "" + +#: order/templates/order/order_base.html:181 +#: order/templates/order/purchase_order_detail.html:101 +#: stock/templates/stock/location.html:42 +msgid "Create new stock location" +msgstr "" + +#: order/templates/order/order_cancel.html:8 +msgid "Cancelling this order means that the order and line items will no longer be editable." msgstr "" #: order/templates/order/order_complete.html:7 @@ -2826,10 +2853,10 @@ msgid "This order has line items which have not been marked as received." msgstr "" #: order/templates/order/order_complete.html:11 -msgid "Marking this order as complete will remove these line items." +msgid "Completing this order means that the order and line items will no longer be editable." msgstr "" -#: order/templates/order/order_issue.html:7 +#: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." msgstr "" @@ -2881,11 +2908,13 @@ msgid "Select Purchase Order" msgstr "" #: order/templates/order/order_wizard/select_pos.html:45 -msgid "Create new purchase order for {{ supplier.name }}" +#, python-format +msgid "Create new purchase order for %(name)s" msgstr "" #: order/templates/order/order_wizard/select_pos.html:68 -msgid "Select a purchase order for" +#, python-format +msgid "Select a purchase order for %(name)s" msgstr "" #: order/templates/order/po_attachments.html:12 @@ -2907,43 +2936,29 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1108 -#: order/views.py:1191 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 +#: order/views.py:1203 msgid "Add Line Item" msgstr "" -#: order/templates/order/purchase_order_detail.html:45 -#: order/templates/order/purchase_order_detail.html:125 -#: part/templates/part/category.html:185 part/templates/part/category.html:227 -#: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 -msgid "New Location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:46 -#: order/templates/order/purchase_order_detail.html:126 -#: stock/templates/stock/location.html:42 -msgid "Create new stock location" -msgstr "" - -#: order/templates/order/purchase_order_detail.html:139 +#: order/templates/order/purchase_order_detail.html:114 msgid "No line items found" msgstr "" -#: order/templates/order/purchase_order_detail.html:205 +#: order/templates/order/purchase_order_detail.html:180 msgid "Unit Price" msgstr "" -#: order/templates/order/purchase_order_detail.html:246 +#: order/templates/order/purchase_order_detail.html:221 #: order/templates/order/sales_order_detail.html:294 msgid "Edit line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:247 +#: order/templates/order/purchase_order_detail.html:222 msgid "Delete line item" msgstr "" -#: order/templates/order/purchase_order_detail.html:252 +#: order/templates/order/purchase_order_detail.html:227 msgid "Receive line item" msgstr "" @@ -2966,7 +2981,7 @@ msgstr "" #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 -#: users/models.py:38 +#: users/models.py:40 msgid "Parts" msgstr "" @@ -3019,6 +3034,10 @@ msgstr "" msgid "Warning" msgstr "" +#: order/templates/order/sales_order_cancel.html:9 +msgid "Cancelling this order means that the order will no longer be editable." +msgstr "" + #: order/templates/order/sales_order_detail.html:13 msgid "Sales Order Items" msgstr "" @@ -3213,65 +3232,65 @@ msgstr "" msgid "No lines specified" msgstr "" -#: order/views.py:1060 +#: order/views.py:1069 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1117 +#: order/views.py:1129 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1123 +#: order/views.py:1135 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1242 order/views.py:1260 +#: order/views.py:1254 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1276 order/views.py:1288 +#: order/views.py:1288 order/views.py:1300 msgid "Delete Line Item" msgstr "" -#: order/views.py:1281 order/views.py:1293 +#: order/views.py:1293 order/views.py:1305 msgid "Deleted line item" msgstr "" -#: order/views.py:1306 +#: order/views.py:1318 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1351 +#: order/views.py:1363 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1367 +#: order/views.py:1379 msgid "Select line item" msgstr "" -#: order/views.py:1398 +#: order/views.py:1410 msgid "No matching item for serial" msgstr "" -#: order/views.py:1408 +#: order/views.py:1420 msgid "is not in stock" msgstr "" -#: order/views.py:1416 +#: order/views.py:1428 msgid "already allocated to an order" msgstr "" -#: order/views.py:1470 +#: order/views.py:1482 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1544 +#: order/views.py:1556 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1559 +#: order/views.py:1571 msgid "Remove allocation" msgstr "" @@ -3457,7 +3476,7 @@ msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 #: templates/InvenTree/search.html:127 templates/stats.html:63 -#: users/models.py:37 +#: users/models.py:39 msgid "Part Categories" msgstr "" @@ -4004,7 +4023,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2270 +#: part/templates/part/category.html:29 part/views.py:2282 msgid "Create new part category" msgstr "" @@ -4694,63 +4713,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2069 +#: part/views.py:2081 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2079 +#: part/views.py:2091 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2086 +#: part/views.py:2098 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2094 +#: part/views.py:2106 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2144 +#: part/views.py:2156 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2158 +#: part/views.py:2170 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2218 +#: part/views.py:2230 msgid "Edit Part Category" msgstr "" -#: part/views.py:2256 +#: part/views.py:2268 msgid "Delete Part Category" msgstr "" -#: part/views.py:2262 +#: part/views.py:2274 msgid "Part category was deleted" msgstr "" -#: part/views.py:2314 +#: part/views.py:2326 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2415 +#: part/views.py:2427 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2471 +#: part/views.py:2483 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2490 +#: part/views.py:2502 msgid "Create BOM Item" msgstr "" -#: part/views.py:2560 +#: part/views.py:2572 msgid "Edit BOM item" msgstr "" -#: part/views.py:2616 +#: part/views.py:2628 msgid "Confim BOM item deletion" msgstr "" @@ -5301,15 +5320,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:164 -#: stock/templates/stock/location.html:65 templates/stock_table.html:56 +#: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:54 +#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 msgid "Remove stock" msgstr "" @@ -5503,7 +5522,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:39 +#: templates/stats.html:76 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5689,7 +5708,7 @@ msgstr "" msgid "Add Stock Items" msgstr "" -#: stock/views.py:1001 users/models.py:180 +#: stock/views.py:1001 users/models.py:183 msgid "Add" msgstr "" @@ -5867,6 +5886,31 @@ msgstr "" msgid "No stock location set" msgstr "" +#: templates/InvenTree/settings/appearance.html:10 +msgid "Theme Settings" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:17 +msgid "Color Themes" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:29 +#, python-format +msgid "" +"\n" +" The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" +" Please select another color theme :)\n" +" " +msgstr "" + +#: templates/InvenTree/settings/appearance.html:39 +msgid "Language" +msgstr "" + +#: templates/InvenTree/settings/appearance.html:61 +msgid "Set Language" +msgstr "" + #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" msgstr "" @@ -5950,7 +5994,7 @@ msgstr "" msgid "Stock Settings" msgstr "" -#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:49 +#: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" msgstr "" @@ -5964,7 +6008,7 @@ msgid "Account" msgstr "" #: templates/InvenTree/settings/tabs.html:9 -msgid "Theme" +msgid "Appearance" msgstr "" #: templates/InvenTree/settings/tabs.html:13 @@ -5983,22 +6027,6 @@ msgstr "" msgid "Categories" msgstr "" -#: templates/InvenTree/settings/theme.html:10 -msgid "Theme Settings" -msgstr "" - -#: templates/InvenTree/settings/theme.html:17 -msgid "Color Themes" -msgstr "" - -#: templates/InvenTree/settings/theme.html:29 -#, python-format -msgid "\n" -"\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
\n" -"\t\tPlease select another color theme :)\n" -"\t" -msgstr "" - #: templates/InvenTree/settings/user.html:16 msgid "User Information" msgstr "" @@ -6061,13 +6089,23 @@ msgid "View Code on GitHub" msgstr "" #: templates/about.html:63 -msgid "Get the App" +msgid "Credits" msgstr "" #: templates/about.html:68 +msgid "Mobile App" +msgstr "" + +#: templates/about.html:73 msgid "Submit Bug Report" msgstr "" +#: templates/about.html:82 templates/js/modals.js:550 +#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 +#: templates/modals.html:93 +msgid "Close" +msgstr "" + #: templates/attachment_table.html:6 msgid "Add Attachment" msgstr "" @@ -6263,7 +6301,7 @@ msgid "Quantity Per" msgstr "" #: templates/js/build.js:638 templates/js/build.js:1056 -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order stock" msgstr "" @@ -6396,11 +6434,6 @@ msgstr "" msgid "Submit" msgstr "" -#: templates/js/modals.js:550 templates/js/modals.js:809 -#: templates/modals.html:28 templates/modals.html:52 templates/modals.html:93 -msgid "Close" -msgstr "" - #: templates/js/modals.js:760 msgid "Invalid response from server" msgstr "" @@ -6974,6 +7007,10 @@ msgstr "" msgid "Form errors exist" msgstr "" +#: templates/navbar.html:13 +msgid "Toggle navigation" +msgstr "" + #: templates/navbar.html:33 msgid "Buy" msgstr "" @@ -6986,7 +7023,7 @@ msgstr "" msgid "Scan Barcode" msgstr "" -#: templates/navbar.html:77 users/models.py:36 +#: templates/navbar.html:77 users/models.py:38 msgid "Admin" msgstr "" @@ -7118,43 +7155,43 @@ msgstr "" msgid "Print test reports" msgstr "" -#: templates/stock_table.html:54 +#: templates/stock_table.html:55 msgid "Add to selected stock items" msgstr "" -#: templates/stock_table.html:55 +#: templates/stock_table.html:56 msgid "Remove from selected stock items" msgstr "" -#: templates/stock_table.html:56 +#: templates/stock_table.html:57 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:57 +#: templates/stock_table.html:58 msgid "Move stock" msgstr "" -#: templates/stock_table.html:58 +#: templates/stock_table.html:59 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change status" msgstr "" -#: templates/stock_table.html:59 +#: templates/stock_table.html:60 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:62 +#: templates/stock_table.html:63 msgid "Delete Stock" msgstr "" @@ -7190,35 +7227,34 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:167 +#: users/models.py:170 msgid "Permission set" msgstr "" -#: users/models.py:175 +#: users/models.py:178 msgid "Group" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "View" msgstr "" -#: users/models.py:178 +#: users/models.py:181 msgid "Permission to view items" msgstr "" -#: users/models.py:180 +#: users/models.py:183 msgid "Permission to add items" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Change" msgstr "" -#: users/models.py:182 +#: users/models.py:185 msgid "Permissions to edit items" msgstr "" -#: users/models.py:184 +#: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/tasks.py b/tasks.py index 6eed4c488e..37cbc71eab 100644 --- a/tasks.py +++ b/tasks.py @@ -185,7 +185,7 @@ def translate(c): """ # Translate applicable .py / .html / .js files - manage(c, "makemessages --all -e py,html,js") + manage(c, "makemessages --all -e py,html,js --no-wrap") manage(c, "compilemessages") path = os.path.join('InvenTree', 'script', 'translation_stats.py') From 9773fee50bd4143c461e48a2e6208239e79b05ce Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 5 May 2021 12:40:48 -0400 Subject: [PATCH 072/300] Validation of matching fields is working --- InvenTree/common/files.py | 31 ++-- InvenTree/order/forms.py | 6 +- .../order/order_wizard/match_fields.html | 1 - InvenTree/order/views.py | 145 ++++++++++++------ 4 files changed, 121 insertions(+), 62 deletions(-) diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py index ab73ec4f1e..d1c8a924b1 100644 --- a/InvenTree/common/files.py +++ b/InvenTree/common/files.py @@ -43,27 +43,42 @@ class FileManager: # Update headers self.update_headers() - def process(self, file): - """ Process file """ + @classmethod + def validate(cls, file): + """ Validate file extension and data """ - self.data = None + cleaned_data = None ext = os.path.splitext(file.name)[-1].lower() if ext in ['.csv', '.tsv', ]: # These file formats need string decoding raw_data = file.read().decode('utf-8') + # Reset stream position to beginning of file + file.seek(0) elif ext in ['.xls', '.xlsx']: raw_data = file.read() + # Reset stream position to beginning of file + file.seek(0) else: raise ValidationError(_(f'Unsupported file format: {ext}')) try: - self.data = tablib.Dataset().load(raw_data) + cleaned_data = tablib.Dataset().load(raw_data) except tablib.UnsupportedFormat: - raise ValidationError(_(f'Error reading {self.name} file (invalid format)')) + raise ValidationError(_('Error reading file (invalid format)')) except tablib.core.InvalidDimensions: - raise ValidationError(_(f'Error reading {self.name} file (incorrect dimension)')) + raise ValidationError(_('Error reading file (incorrect dimension)')) + except KeyError: + # TODO: Find fix for XLSX format as it keeps on returning a KeyError + raise ValidationError(_('Error reading file (data could be corrupted)')) + + return cleaned_data + + def process(self, file): + """ Process file """ + + self.data = self.__class__.validate(file) def update_headers(self): """ Update headers """ @@ -74,7 +89,7 @@ class FileManager: """ Setup headers depending on the file name """ if not self.name: - return False + return if self.name == 'order': self.REQUIRED_HEADERS = [ @@ -94,8 +109,6 @@ class FileManager: # Update headers self.update_headers() - return True - def guess_header(self, header, threshold=80): """ Try to match a header (from the file) to a list of known headers diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 858679ffdf..b99c09caba 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -298,11 +298,11 @@ class UploadFile(forms.Form): def clean_file(self): file = self.cleaned_data['file'] - # Create a FileManager object - will perform initial data validation + # Validate file using FileManager class - will perform initial data validation # (and raise a ValidationError if there is something wrong with the file) - file_manager = FileManager(file=file, name='order') + FileManager.validate(file) - return file_manager + return file class MatchField(forms.Form): diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index 1ac1f30997..d1385d031b 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -25,7 +25,6 @@ {% endblock form_buttons_top %} {% block form_content %} - {{ wizard.form }} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index ee11609b35..d671fd694d 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -29,6 +29,7 @@ from part.models import Part from common.models import InvenTreeSetting from common.views import MultiStepFormView +from common.files import FileManager from . import forms as order_forms @@ -590,6 +591,7 @@ class PurchaseOrderUpload(MultiStepFormView): headers = None rows = None columns = None + missing_columns = None def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -603,12 +605,13 @@ class PurchaseOrderUpload(MultiStepFormView): # print(f'{self.headers}') if self.columns: context.update({'columns': self.columns}) - # print(f'{self.columns}') + print(f'{self.columns}') if self.rows: context.update({'rows': self.rows}) # print(f'{self.rows}') + if self.missing_columns: + context.update({'missing_columns': self.missing_columns}) - print(f'{context=}') return context def getTableDataFromForm(self, form_data): @@ -623,10 +626,6 @@ class PurchaseOrderUpload(MultiStepFormView): """ - if not self.file_manager: - print('Lost file manager...') - return - # Map the columns self.column_names = {} self.column_selections = {} @@ -746,68 +745,116 @@ class PurchaseOrderUpload(MultiStepFormView): for col in self.file_manager.PART_MATCH_HEADERS: self.missing_columns.append(col) - def handleFileUpload(self, form): - """ Process file upload and setup fields form """ + def getFileManager(self, form=None): + """ Create FileManager instance from upload file """ + + if self.file_manager: + return - # Check if user completed file upload if self.steps.current == 'upload': - # Copy FileManager instance from form - self.file_manager = form.cleaned_data['file'] - print(f'{self.file_manager=}') - # Setup FileManager for order upload - setup_valid = self.file_manager.setup() - if setup_valid: - # Set headers - self.headers = self.file_manager.HEADERS - # Set columns and rows - self.columns = self.file_manager.columns() - self.rows = self.file_manager.rows() + # Get file from form data + order_file = form.cleaned_data['file'] + self.file_manager = FileManager(file=order_file, name='order') + else: + # Retrieve stored files from upload step + upload_files = self.storage.get_step_files('upload') + # Get file + order_file = upload_files.get('upload-file', None) + if order_file: + self.file_manager = FileManager(file=order_file, name='order') - # Save FileManager - # self.storage.set_step_data('file', self.file_manager) + def setupFieldSelection(self, form): + """ Setup fields form """ + + # Get FileManager + self.getFileManager(form) + # Setup headers + self.file_manager.setup() + # Set headers + self.headers = self.file_manager.HEADERS + # Set columns and rows + self.columns = self.file_manager.columns() + self.rows = self.file_manager.rows() - def handleFieldSelection(self, form_data): + def handleFieldSelection(self, form): """ Process field matching """ + # Update headers + if self.file_manager: + self.file_manager.setup() + else: + return False + # Extract form data - self.getTableDataFromForm(form_data) + self.getTableDataFromForm(form.data) valid = len(self.missing_columns) == 0 and not self.duplicates - if not valid: - raise ValidationError('Invalid data') + return valid - def handlePartSelection(self, form_data): + def handlePartSelection(self, form): pass - # print(f'{form_data=}') - - # def process_step(self, form): - # print(f'{self.steps.current=} | {form.data}') - # return self.get_form_step_data(form) def get_form_step_data(self, form): - print(f'{self.steps.current=}\n{form.data=}') - print(f'{self.file_manager=}') + """ Process form data after it has been posted """ + + # print(f'{self.steps.current=}\n{form.data=}') + + # Retrieve FileManager instance from uploaded file + self.getFileManager(form) + # print(f'{self.file_manager=}') + # Process steps if self.steps.current == 'upload': - self.handleFileUpload(form) - if self.steps.current == 'fields': - self.handleFieldSelection(form.data) - elif self.steps.current == 'parts': - self.handlePartSelection(form.data) + self.setupFieldSelection(form) + # elif self.steps.current == 'fields': + # self.handleFieldSelection(form) + # elif self.steps.current == 'parts': + # self.handlePartSelection(form) return form.data - - # def get_all_cleaned_data(self): - # cleaned_data = super().get_all_cleaned_data() - # print(f'{self.steps.current=} | {cleaned_data}') - # return cleaned_data - # def post(self, request, *args, **kwargs): - # """ Perform the various 'POST' requests required. - # """ - # print('Posting!') - # return super().post(*args, **kwargs) + def validate(self, step, form): + """ Validate forms """ + + valid = False + + # Process steps + if step == 'upload': + # Validation is done during POST + valid = True + elif step == 'fields': + # Retrieve FileManager instance from uploaded file + self.getFileManager(form) + # Validate user form data + valid = self.handleFieldSelection(form) + + if not valid: + form.add_error(None, 'Fields matching failed') + # Set headers + self.headers = self.file_manager.HEADERS + + elif step == 'parts': + valid = self.handlePartSelection(form) + + return valid + + def post(self, request, *args, **kwargs): + """ Perform validations before posting data """ + + wizard_goto_step = self.request.POST.get('wizard_goto_step', None) + + form = self.get_form(data=self.request.POST, files=self.request.FILES) + + print(f'\nCurrent step = {self.steps.current}') + form_valid = self.validate(self.steps.current, form) + + if not form_valid and not wizard_goto_step: + # Re-render same step + return self.render(form) + + print('\nPosting... ') + return super().post(*args, **kwargs) def done(self, form_list, **kwargs): return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) From 2cd1df691b2165509e4df5c0377b9b810e3f832e Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 5 May 2021 13:16:40 -0400 Subject: [PATCH 073/300] Working towards part matching --- .../order/order_wizard/match_fields.html | 4 +- .../order/order_wizard/match_parts.html | 8 +- InvenTree/order/views.py | 94 ++++++++++++++++++- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index d1385d031b..e837279ccb 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -18,9 +18,9 @@ {% endblock form_alert %} {% block form_buttons_top %} - {% if wizard.steps.prev %} + {% comment %} {% if wizard.steps.prev %} - {% endif %} + {% endif %} {% endcomment %} {% endblock form_buttons_top %} diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index 735d847b87..2cf4aa1ea2 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -12,9 +12,9 @@ {% endblock form_alert %} {% block form_buttons_top %} - {% if wizard.steps.prev %} + {% comment %} {% if wizard.steps.prev %} - {% endif %} + {% endif %} {% endcomment %} {% endblock form_buttons_top %} @@ -25,7 +25,7 @@ {% trans "Row" %} {% trans "Select Part" %} - {% for col in bom_columns %} + {% for col in columns %} @@ -39,7 +39,7 @@ - {% for row in bom_rows %} + {% for row in rows %} `; diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index d57c0da98a..09c15eb865 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -287,7 +287,7 @@ $("#so-lines-table").inventreeTable({ html += makeIconButton('fa-hashtag icon-green', 'button-add-by-sn', pk, '{% trans "Allocate serial numbers" %}'); } - html += makeIconButton('fa-sign-in-alt icon-green', 'button-add', pk, '{% trans "Allocate stock" %}'); + html += makeIconButton('fa-sign-in-alt icon-green', 'button-add', pk, '{% trans "Allocate stock" %}'); if (part.purchaseable) { html += makeIconButton('fa-shopping-cart', 'button-buy', row.part, '{% trans "Purchase stock" %}'); From 40e8ed9e5b5d368100b976d981431f983d33595e Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 5 May 2021 15:28:04 -0400 Subject: [PATCH 078/300] Match parts view is now populated correctly --- .../order/order_wizard/match_fields.html | 2 +- .../order/order_wizard/match_parts.html | 13 +--- InvenTree/order/views.py | 65 +++++++++++++------ 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index e837279ccb..08fce9802d 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -72,7 +72,7 @@ {% for item in row.data %} - {{ item }} + {{ item.cell }} {% endfor %} diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index 2cf4aa1ea2..6714c0c11a 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -66,22 +66,11 @@ {% for item in row.data %} - {% if item.column.guess == 'Part' %} - {{ item.cell }} - {% if row.errors.part %} -

{{ row.errors.part }}

- {% endif %} - {% elif item.column.guess == 'Quantity' %} + {% if item.column.guess == 'Quantity' %} {% if row.errors.quantity %}

{{ row.errors.quantity }}

{% endif %} - {% elif item.column.guess == 'Reference' %} - - {% elif item.column.guess == 'Note' %} - - {% elif item.column.guess == 'Overage' %} - {% else %} {{ item.cell }} {% endif %} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index 6679f0031f..d054110818 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -23,7 +23,7 @@ from .models import SalesOrder, SalesOrderLineItem, SalesOrderAttachment from .models import SalesOrderAllocation from .admin import POLineItemResource from build.models import Build -from company.models import Company, ManufacturerPart, SupplierPart +from company.models import Company, SupplierPart # ManufacturerPart from stock.models import StockItem, StockLocation from part.models import Part @@ -592,6 +592,7 @@ class PurchaseOrderUpload(MultiStepFormView): rows = None columns = None missing_columns = None + allowed_parts = None def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -605,8 +606,22 @@ class PurchaseOrderUpload(MultiStepFormView): # print(f'{self.headers}') if self.columns: context.update({'columns': self.columns}) - print(f'{self.columns}') + # print(f'{self.columns}') if self.rows: + for row in self.rows: + row_data = row['data'] + + data = [] + + for idx, item in enumerate(row_data): + data.append({ + 'cell': item, + 'idx': idx, + 'column': self.columns[idx] + }) + + row['data'] = data + context.update({'rows': self.rows}) # print(f'{self.rows}') if self.missing_columns: @@ -764,11 +779,11 @@ class PurchaseOrderUpload(MultiStepFormView): """ # Fields prefixed with "Part_" can be used to do "smart matching" against Part objects in the database - s_idx = self.getColumnIndex('Supplier_SKU') - m_idx = self.getColumnIndex('Manufacturer_MPN') q_idx = self.getColumnIndex('Quantity') - p_idx = self.getColumnIndex('Unit_Price') - e_idx = self.getColumnIndex('Extended_Price') + s_idx = self.getColumnIndex('Supplier_SKU') + # m_idx = self.getColumnIndex('Manufacturer_MPN') + # p_idx = self.getColumnIndex('Unit_Price') + # e_idx = self.getColumnIndex('Extended_Price') for row in self.rows: @@ -779,7 +794,7 @@ class PurchaseOrderUpload(MultiStepFormView): exact_match_part = None # A list of potential Part matches - part_options = SupplierPart.objects.all() + part_options = self.allowed_parts # Check if there is a column corresponding to "quantity" if q_idx >= 0: @@ -797,23 +812,23 @@ class PurchaseOrderUpload(MultiStepFormView): # Check if there is a column corresponding to "Supplier SKU" if s_idx >= 0: - row['part_sku'] = row['data'][s_idx] + sku = row['data'][s_idx] try: # Attempt SupplierPart lookup based on SKU value - exact_match_part = SupplierPart.objects.get(SKU=row['part_sku']) - except (ValueError, SupplierPart.DoesNotExist): + exact_match_part = SupplierPart.objects.get(SKU__contains=sku) + except (ValueError, SupplierPart.DoesNotExist, SupplierPart.MultipleObjectsReturned): exact_match_part = None # Check if there is a column corresponding to "Manufacturer MPN" - if m_idx >= 0: - row['part_mpn'] = row['data'][m_idx] + # if m_idx >= 0: + # row['part_mpn'] = row['data'][m_idx] - # try: - # # Attempt ManufacturerPart lookup based on MPN value - # exact_match_part = ManufacturerPart.objects.get(MPN=row['part_mpn']) - # except (ValueError, ManufacturerPart.DoesNotExist): - # exact_match_part = None + # try: + # # Attempt ManufacturerPart lookup based on MPN value + # exact_match_part = ManufacturerPart.objects.get(MPN=row['part_mpn']) + # except (ValueError, ManufacturerPart.DoesNotExist): + # exact_match_part = None # Supply list of part options for each row, sorted by how closely they match the part name row['part_options'] = part_options @@ -825,6 +840,10 @@ class PurchaseOrderUpload(MultiStepFormView): # If there is an exact match based on SKU or MPN, use that row['part_match'] = exact_match_part + def updatePartSelectionColumns(self, form): + # for idx, row in enumerate(self.rows): + # print(f'{idx} | {row}\n\n') + pass def getFileManager(self, form=None): """ Create FileManager instance from upload file """ @@ -860,6 +879,9 @@ class PurchaseOrderUpload(MultiStepFormView): def handleFieldSelection(self, form): """ Process field matching """ + # Retrieve FileManager instance from uploaded file + self.getFileManager(form) + # Update headers if self.file_manager: self.file_manager.setup() @@ -875,6 +897,9 @@ class PurchaseOrderUpload(MultiStepFormView): def handlePartSelection(self, form): + # Retrieve FileManager instance from uploaded file + self.getFileManager(form) + # Extract form data self.getTableDataFromForm(form.data) @@ -893,8 +918,10 @@ class PurchaseOrderUpload(MultiStepFormView): if self.steps.current == 'upload': self.setupFieldSelection(form) elif self.steps.current == 'fields': + self.allowed_parts = SupplierPart.objects.all() + self.rows = self.file_manager.rows() self.preFillSelections() - print(self.rows) + self.updatePartSelectionColumns(form) # elif self.steps.current == 'parts': # self.handlePartSelection(form) @@ -910,8 +937,6 @@ class PurchaseOrderUpload(MultiStepFormView): # Validation is done during POST valid = True elif step == 'fields': - # Retrieve FileManager instance from uploaded file - self.getFileManager(form) # Validate user form data valid = self.handleFieldSelection(form) From 287a05ddc5cece2f534c5d81dc575d02b5a1935c Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 5 May 2021 21:48:58 +0200 Subject: [PATCH 079/300] clearer spacing in html --- .../part/templates/part/part_pricing.html | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index b14be2c61f..9922813210 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -19,9 +19,10 @@ {{ quantity }} - {% if part.supplier_count > 0 %} + +{% if part.supplier_count > 0 %}

{% trans 'Supplier Pricing' %}

- +
{% if min_total_buy_price %} @@ -42,12 +43,12 @@ {% endif %} -
{% trans 'Unit Cost' %}
- {% endif %} + +{% endif %} - {% if part.bom_count > 0 %} +{% if part.bom_count > 0 %}

{% trans 'BOM Pricing' %}

- +
{% if min_total_bom_price %} @@ -75,8 +76,8 @@ {% endif %} -
{% trans 'Unit Cost' %}
- {% endif %} + +{% endif %} {% if min_unit_buy_price or min_unit_bom_price %} {% else %} @@ -84,7 +85,5 @@ {% trans 'No pricing information is available for this part.' %}
{% endif %} -
- {% endblock %} \ No newline at end of file From 1a227faec4fa3f0d1fe5a77546e56771283dff22 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 5 May 2021 23:42:52 +0200 Subject: [PATCH 080/300] abstracting get_price --- InvenTree/common/models.py | 68 +++++++++++++++++++++++++++++++++++++ InvenTree/company/models.py | 65 +---------------------------------- 2 files changed, 69 insertions(+), 64 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index bc2ca4214b..4280177629 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -7,6 +7,8 @@ These models are 'generic' and do not fit a particular business logic object. from __future__ import unicode_literals import os +import decimal +import math from django.db import models, transaction from django.db.utils import IntegrityError, OperationalError @@ -730,6 +732,72 @@ class PriceBreak(models.Model): return converted.amount +def get_price(instance, quantity, moq=True, multiples=True, currency=None): + """ Calculate the price based on quantity price breaks. + + - Don't forget to add in flat-fee cost (base_cost field) + - If MOQ (minimum order quantity) is required, bump quantity + - If order multiples are to be observed, then we need to calculate based on that, too + """ + + price_breaks = instance.price_breaks.all() + + # No price break information available? + if len(price_breaks) == 0: + return None + + # Check if quantity is fraction and disable multiples + multiples = (quantity % 1 == 0) + + # Order multiples + if multiples: + quantity = int(math.ceil(quantity / instance.multiple) * instance.multiple) + + pb_found = False + pb_quantity = -1 + pb_cost = 0.0 + + if currency is None: + # Default currency selection + currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') + + pb_min = None + for pb in instance.price_breaks.all(): + # Store smallest price break + if not pb_min: + pb_min = pb + + # Ignore this pricebreak (quantity is too high) + if pb.quantity > quantity: + continue + + pb_found = True + + # If this price-break quantity is the largest so far, use it! + if pb.quantity > pb_quantity: + pb_quantity = pb.quantity + + # Convert everything to the selected currency + pb_cost = pb.convert_to(currency) + + # Use smallest price break + if not pb_found and pb_min: + # Update price break information + pb_quantity = pb_min.quantity + pb_cost = pb_min.convert_to(currency) + # Trigger cost calculation using smallest price break + pb_found = True + + # Convert quantity to decimal.Decimal format + quantity = decimal.Decimal(f'{quantity}') + + if pb_found: + cost = pb_cost * quantity + return InvenTree.helpers.normalize(cost + instance.base_cost) + else: + return None + + class ColorTheme(models.Model): """ Color Theme Setting """ diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 89a3f6c9bf..baac95d44d 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -558,70 +558,7 @@ class SupplierPart(models.Model): price=price ) - def get_price(self, quantity, moq=True, multiples=True, currency=None): - """ Calculate the supplier price based on quantity price breaks. - - - Don't forget to add in flat-fee cost (base_cost field) - - If MOQ (minimum order quantity) is required, bump quantity - - If order multiples are to be observed, then we need to calculate based on that, too - """ - - price_breaks = self.price_breaks.all() - - # No price break information available? - if len(price_breaks) == 0: - return None - - # Check if quantity is fraction and disable multiples - multiples = (quantity % 1 == 0) - - # Order multiples - if multiples: - quantity = int(math.ceil(quantity / self.multiple) * self.multiple) - - pb_found = False - pb_quantity = -1 - pb_cost = 0.0 - - if currency is None: - # Default currency selection - currency = common.models.InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') - - pb_min = None - for pb in self.price_breaks.all(): - # Store smallest price break - if not pb_min: - pb_min = pb - - # Ignore this pricebreak (quantity is too high) - if pb.quantity > quantity: - continue - - pb_found = True - - # If this price-break quantity is the largest so far, use it! - if pb.quantity > pb_quantity: - pb_quantity = pb.quantity - - # Convert everything to the selected currency - pb_cost = pb.convert_to(currency) - - # Use smallest price break - if not pb_found and pb_min: - # Update price break information - pb_quantity = pb_min.quantity - pb_cost = pb_min.convert_to(currency) - # Trigger cost calculation using smallest price break - pb_found = True - - # Convert quantity to decimal.Decimal format - quantity = decimal.Decimal(f'{quantity}') - - if pb_found: - cost = pb_cost * quantity - return normalize(cost + self.base_cost) - else: - return None + get_price = common.models.get_price def open_orders(self): """ Return a database query for PO line items for this SupplierPart, From 1b7ade94052178b04cc7a5c8bbbb410a8e94620f Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 5 May 2021 23:47:46 +0200 Subject: [PATCH 081/300] adding in missing parts for full saleprice --- .../migrations/0065_auto_20210505_2144.py | 24 ++++++++++++ InvenTree/part/models.py | 38 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 InvenTree/part/migrations/0065_auto_20210505_2144.py diff --git a/InvenTree/part/migrations/0065_auto_20210505_2144.py b/InvenTree/part/migrations/0065_auto_20210505_2144.py new file mode 100644 index 0000000000..328ce1f588 --- /dev/null +++ b/InvenTree/part/migrations/0065_auto_20210505_2144.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2 on 2021-05-05 21:44 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0064_auto_20210404_2016'), + ] + + operations = [ + migrations.AddField( + model_name='part', + name='base_cost', + field=models.DecimalField(decimal_places=3, default=0, help_text='Minimum charge (e.g. stocking fee)', max_digits=10, validators=[django.core.validators.MinValueValidator(0)], verbose_name='base cost'), + ), + migrations.AddField( + model_name='part', + name='multiple', + field=models.PositiveIntegerField(default=1, help_text='Sell multiple', validators=[django.core.validators.MinValueValidator(1)], verbose_name='multiple'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 137781ba2b..4c7086f51d 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -1611,6 +1611,44 @@ class Part(MPTTModel): max(buy_price_range[1], bom_price_range[1]) ) + base_cost = models.DecimalField(max_digits=10, decimal_places=3, default=0, validators=[MinValueValidator(0)], verbose_name=_('base cost'), help_text=_('Minimum charge (e.g. stocking fee)')) + + multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], verbose_name=_('multiple'), help_text=_('Sell multiple')) + + get_price = common.models.get_price + + @property + def has_price_breaks(self): + return self.price_breaks.count() > 0 + + @property + def price_breaks(self): + """ Return the associated price breaks in the correct order """ + return self.salepricebreaks.order_by('quantity').all() + + @property + def unit_pricing(self): + return self.get_price(1) + + def add_price_break(self, quantity, price): + """ + Create a new price break for this part + + args: + quantity - Numerical quantity + price - Must be a Money object + """ + + # Check if a price break at that quantity already exists... + if self.price_breaks.filter(quantity=quantity, part=self.pk).exists(): + return + + PartSellPriceBreak.objects.create( + part=self, + quantity=quantity, + price=price + ) + @transaction.atomic def copy_bom_from(self, other, clear=True, **kwargs): """ From 030865f8dd96b45f621c80b5833301786b004c35 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 5 May 2021 23:49:04 +0200 Subject: [PATCH 082/300] sale price in pricing table --- InvenTree/part/templates/part/part_pricing.html | 14 ++++++++++++++ InvenTree/part/views.py | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index 9922813210..df43ed8799 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -79,6 +79,20 @@ {% endif %} +{% if total_part_price %} +

{% trans 'Sale Price' %}

+ + + + + + + + + +
{% trans 'Unit Cost' %}{% include "price.html" with price=unit_part_price %}
{% trans 'Total Cost' %}{% include "price.html" with price=total_part_price %}
+{% endif %} + {% if min_unit_buy_price or min_unit_bom_price %} {% else %}
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index b7bebb6d05..5af90cb383 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -2055,6 +2055,12 @@ class PartPricing(AjaxView): ctx['max_total_bom_price'] = max_bom_price ctx['max_unit_bom_price'] = max_unit_bom_price + # part pricing information + part_price = part.get_price(quantity) + if part_price is not None: + ctx['total_part_price'] = round(part_price, 3) + ctx['unit_part_price'] = round(part_price / quantity, 3) + return ctx def get(self, request, *args, **kwargs): From efa9da2ce1b38a98afb09f3b7ab2a965529a8432 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 00:00:13 +0200 Subject: [PATCH 083/300] removed unused imports --- InvenTree/company/models.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index baac95d44d..32f1d07a33 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -6,8 +6,6 @@ Company database model definitions from __future__ import unicode_literals import os -import decimal -import math from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinValueValidator @@ -26,7 +24,6 @@ from markdownx.models import MarkdownxField from stdimage.models import StdImageField from InvenTree.helpers import getMediaUrl, getBlankImage, getBlankThumbnail -from InvenTree.helpers import normalize from InvenTree.fields import InvenTreeURLField from InvenTree.status_codes import PurchaseOrderStatus From 66f198baa93150a8e1602e4bb6c8836eb20d71df Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 00:17:46 +0200 Subject: [PATCH 084/300] removing duplicate information in pricing table --- InvenTree/part/templates/part/part_pricing.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index df43ed8799..af916a43fd 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -4,11 +4,6 @@ {% block pre_form_content %} -
-{% blocktrans %}Pricing information for:
{{part}}.{% endblocktrans %} -
- -

{% trans 'Quantity' %}

From f9463fa277bf0d7da0284ed843849e83a560f10b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 00:33:34 +0200 Subject: [PATCH 085/300] fixes navbar-layout shift with narrow dollar-sign --- InvenTree/part/templates/part/navbar.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index d8750a49a5..df49841e31 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -91,7 +91,7 @@ {% if part.salable and roles.sales_order.view %}
  • - + {% trans "Sale Price" %}
  • From 1259374822ae330ae54bcb7c6745f2ecd2cb69db Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 00:37:45 +0200 Subject: [PATCH 086/300] removes layout-shift due to typo in menubar --- InvenTree/part/templates/part/sale_prices.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/templates/part/sale_prices.html b/InvenTree/part/templates/part/sale_prices.html index ce50c1f20d..f19d65a59a 100644 --- a/InvenTree/part/templates/part/sale_prices.html +++ b/InvenTree/part/templates/part/sale_prices.html @@ -2,7 +2,7 @@ {% load static %} {% load i18n %} -{% block menubar %}} +{% block menubar %} {% include 'part/navbar.html' with tab='sales-prices' %} {% endblock %} From f2b0717d10db0b831d6a8045fed3aa4febbdf18c Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 12:11:38 +0200 Subject: [PATCH 087/300] removes all lines consisting only of spaces this really bothers me for some reason - nothing technical --- InvenTree/InvenTree/api_tester.py | 2 +- InvenTree/InvenTree/context.py | 2 +- InvenTree/InvenTree/exchange.py | 2 +- InvenTree/InvenTree/fields.py | 2 +- InvenTree/InvenTree/helpers.py | 24 ++--- InvenTree/InvenTree/models.py | 2 +- InvenTree/InvenTree/permissions.py | 2 +- InvenTree/InvenTree/serializers.py | 2 +- InvenTree/InvenTree/status.py | 2 +- InvenTree/InvenTree/status_codes.py | 2 +- InvenTree/InvenTree/test_api.py | 2 +- InvenTree/InvenTree/test_tasks.py | 2 +- InvenTree/InvenTree/tests.py | 6 +- InvenTree/InvenTree/urls.py | 4 +- InvenTree/InvenTree/validators.py | 2 +- InvenTree/InvenTree/views.py | 24 ++--- InvenTree/barcodes/api.py | 8 +- InvenTree/barcodes/barcode.py | 2 +- InvenTree/barcodes/tests.py | 4 +- InvenTree/build/api.py | 4 +- InvenTree/build/models.py | 28 ++--- InvenTree/build/test_api.py | 4 +- InvenTree/build/test_build.py | 10 +- InvenTree/build/tests.py | 16 +-- InvenTree/build/views.py | 40 +++---- InvenTree/common/admin.py | 2 +- InvenTree/common/models.py | 12 +-- InvenTree/common/settings.py | 2 +- InvenTree/common/test_views.py | 2 +- InvenTree/common/tests.py | 2 +- InvenTree/common/views.py | 2 +- InvenTree/company/api.py | 10 +- InvenTree/company/forms.py | 2 +- InvenTree/company/models.py | 20 ++-- InvenTree/company/serializers.py | 6 +- InvenTree/company/test_migrations.py | 12 +-- InvenTree/company/test_views.py | 12 +-- InvenTree/company/tests.py | 10 +- InvenTree/company/urls.py | 2 +- InvenTree/company/views.py | 22 ++-- InvenTree/label/api.py | 6 +- InvenTree/label/apps.py | 2 +- InvenTree/label/models.py | 4 +- InvenTree/label/test_api.py | 2 +- InvenTree/order/forms.py | 2 +- InvenTree/order/models.py | 18 ++-- InvenTree/order/serializers.py | 16 +-- InvenTree/order/test_api.py | 4 +- InvenTree/order/test_sales_order.py | 8 +- InvenTree/order/test_views.py | 10 +- InvenTree/order/tests.py | 6 +- InvenTree/order/views.py | 50 ++++----- InvenTree/part/admin.py | 6 +- InvenTree/part/api.py | 26 ++--- InvenTree/part/apps.py | 2 +- InvenTree/part/bom.py | 22 ++-- InvenTree/part/forms.py | 6 +- InvenTree/part/models.py | 46 ++++---- InvenTree/part/serializers.py | 8 +- .../part/templatetags/inventree_extras.py | 6 +- InvenTree/part/test_api.py | 14 +-- InvenTree/part/test_bom_item.py | 6 +- InvenTree/part/test_category.py | 6 +- InvenTree/part/test_migrations.py | 2 +- InvenTree/part/test_param.py | 2 +- InvenTree/part/test_part.py | 6 +- InvenTree/part/test_views.py | 14 +-- InvenTree/part/urls.py | 12 +-- InvenTree/part/views.py | 102 +++++++++--------- InvenTree/plugins/action/action.py | 4 +- InvenTree/report/api.py | 18 ++-- InvenTree/report/models.py | 6 +- InvenTree/report/templatetags/barcode.py | 2 +- InvenTree/report/templatetags/report.py | 2 +- InvenTree/script/translate.py | 2 +- InvenTree/script/translation_stats.py | 2 +- InvenTree/stock/admin.py | 4 +- InvenTree/stock/api.py | 30 +++--- InvenTree/stock/forms.py | 24 ++--- InvenTree/stock/models.py | 24 ++--- InvenTree/stock/serializers.py | 4 +- InvenTree/stock/test_api.py | 16 +-- InvenTree/stock/test_views.py | 12 +-- InvenTree/stock/tests.py | 6 +- InvenTree/stock/urls.py | 2 +- InvenTree/stock/views.py | 76 ++++++------- InvenTree/users/admin.py | 2 +- InvenTree/users/models.py | 8 +- InvenTree/users/test_migrations.py | 2 +- InvenTree/users/tests.py | 6 +- tasks.py | 6 +- 91 files changed, 494 insertions(+), 494 deletions(-) diff --git a/InvenTree/InvenTree/api_tester.py b/InvenTree/InvenTree/api_tester.py index 2e69e40969..eb92bd80c1 100644 --- a/InvenTree/InvenTree/api_tester.py +++ b/InvenTree/InvenTree/api_tester.py @@ -83,7 +83,7 @@ class InvenTreeAPITestCase(APITestCase): self.assertEqual(response.status_code, code) return response - + def post(self, url, data): """ Issue a POST request diff --git a/InvenTree/InvenTree/context.py b/InvenTree/InvenTree/context.py index e072f5a5ea..669b55b0c0 100644 --- a/InvenTree/InvenTree/context.py +++ b/InvenTree/InvenTree/context.py @@ -71,7 +71,7 @@ def status_codes(request): def user_roles(request): """ Return a map of the current roles assigned to the user. - + Roles are denoted by their simple names, and then the permission type. Permissions can be access as follows: diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 04ceabccd8..06de4861ec 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -17,5 +17,5 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): """ Do not get any rates... """ - + return {} diff --git a/InvenTree/InvenTree/fields.py b/InvenTree/InvenTree/fields.py index 155f77c639..c496c1bb22 100644 --- a/InvenTree/InvenTree/fields.py +++ b/InvenTree/InvenTree/fields.py @@ -102,5 +102,5 @@ class RoundingDecimalField(models.DecimalField): } defaults.update(kwargs) - + return super().formfield(**kwargs) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index d5508b7db2..1097c5663b 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -35,7 +35,7 @@ def generateTestKey(test_name): """ Generate a test 'key' for a given test name. This must not have illegal chars as it will be used for dict lookup in a template. - + Tests must be named such that they will have unique keys. """ @@ -102,7 +102,7 @@ def TestIfImageURL(url): '.tif', '.tiff', '.webp', '.gif', ] - + def str2bool(text, test=True): """ Test if a string 'looks' like a boolean value. @@ -137,10 +137,10 @@ def isNull(text): """ Test if a string 'looks' like a null value. This is useful for querying the API against a null key. - + Args: text: Input text - + Returns: True if the text looks like a null value """ @@ -157,7 +157,7 @@ def normalize(d): d = Decimal(d) d = d.normalize() - + # Ref: https://docs.python.org/3/library/decimal.html return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize() @@ -165,14 +165,14 @@ def normalize(d): def increment(n): """ Attempt to increment an integer (or a string that looks like an integer!) - + e.g. 001 -> 002 2 -> 3 AB01 -> AB02 QQQ -> QQQ - + """ value = str(n).strip() @@ -314,7 +314,7 @@ def MakeBarcode(object_name, object_pk, object_data={}, **kwargs): def GetExportFormats(): """ Return a list of allowable file formats for exporting data """ - + return [ 'csv', 'tsv', @@ -327,7 +327,7 @@ def GetExportFormats(): def DownloadFile(data, filename, content_type='application/text'): """ Create a dynamic file for the user to download. - + Args: data: Raw file data (string or bytes) filename: Filename for the file download @@ -525,7 +525,7 @@ def addUserPermission(user, permission): """ Shortcut function for adding a certain permission to a user. """ - + perm = Permission.objects.get(codename=permission) user.user_permissions.add(perm) @@ -576,7 +576,7 @@ def getOldestMigrationFile(app, exclude_extension=True, ignore_initial=True): continue num = int(f.split('_')[0]) - + if oldest_file is None or num < oldest_num: oldest_num = num oldest_file = f @@ -585,7 +585,7 @@ def getOldestMigrationFile(app, exclude_extension=True, ignore_initial=True): oldest_file = oldest_file.replace('.py', '') return oldest_file - + def getNewestMigrationFile(app, exclude_extension=True): """ diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index 8494b52a10..5822f8a19f 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -129,7 +129,7 @@ class InvenTreeTree(MPTTModel): Here an 'item' is considered to be the 'leaf' at the end of each branch, and the exact nature here will depend on the class implementation. - + The default implementation returns zero """ return 0 diff --git a/InvenTree/InvenTree/permissions.py b/InvenTree/InvenTree/permissions.py index 973395a2a0..defb370435 100644 --- a/InvenTree/InvenTree/permissions.py +++ b/InvenTree/InvenTree/permissions.py @@ -17,7 +17,7 @@ class RolePermission(permissions.BasePermission): - PUT - PATCH - DELETE - + Specify the required "role" using the role_required attribute. e.g. diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py index 6b40b8eb31..fa7674723c 100644 --- a/InvenTree/InvenTree/serializers.py +++ b/InvenTree/InvenTree/serializers.py @@ -44,7 +44,7 @@ class InvenTreeModelSerializer(serializers.ModelSerializer): In addition to running validators on the serializer fields, this class ensures that the underlying model is also validated. """ - + # Run any native validation checks first (may throw an ValidationError) data = super(serializers.ModelSerializer, self).validate(data) diff --git a/InvenTree/InvenTree/status.py b/InvenTree/InvenTree/status.py index 5531d4c270..970e88831d 100644 --- a/InvenTree/InvenTree/status.py +++ b/InvenTree/InvenTree/status.py @@ -64,7 +64,7 @@ def is_email_configured(): if not settings.EMAIL_HOST_USER: configured = False - + # Display warning unless in test mode if not settings.TESTING: logger.warning("EMAIL_HOST_USER is not configured") diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index 6294eba06e..c73ef10018 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -16,7 +16,7 @@ class StatusCode: # If the key cannot be found, pass it back if key not in cls.options.keys(): return key - + value = cls.options.get(key, key) color = cls.colors.get(key, 'grey') diff --git a/InvenTree/InvenTree/test_api.py b/InvenTree/InvenTree/test_api.py index 52765db2a7..8435d756fb 100644 --- a/InvenTree/InvenTree/test_api.py +++ b/InvenTree/InvenTree/test_api.py @@ -119,7 +119,7 @@ class APITests(InvenTreeAPITestCase): self.assertNotIn('add', roles[rule]) self.assertNotIn('change', roles[rule]) self.assertNotIn('delete', roles[rule]) - + def test_with_superuser(self): """ Superuser should have *all* roles assigned diff --git a/InvenTree/InvenTree/test_tasks.py b/InvenTree/InvenTree/test_tasks.py index 02e8d14e5e..e9c9d9f01c 100644 --- a/InvenTree/InvenTree/test_tasks.py +++ b/InvenTree/InvenTree/test_tasks.py @@ -37,7 +37,7 @@ class ScheduledTaskTests(TestCase): # Attempt to schedule the same task again InvenTree.tasks.schedule_task(task, schedule_type=Schedule.MINUTES, minutes=5) self.assertEqual(self.get_tasks(task).count(), 1) - + # But the 'minutes' should have been updated t = Schedule.objects.get(func=task) self.assertEqual(t.minutes, 5) diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index af812fe8a3..d65829cf8e 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -97,7 +97,7 @@ class TestHelpers(TestCase): self.assertEqual(helpers.getMediaUrl('xx/yy.png'), '/media/xx/yy.png') def testDecimal2String(self): - + self.assertEqual(helpers.decimal2string(Decimal('1.2345000')), '1.2345') self.assertEqual(helpers.decimal2string('test'), 'test') @@ -205,7 +205,7 @@ class TestMPTT(TestCase): child = StockLocation.objects.get(pk=5) parent.parent = child - + with self.assertRaises(InvalidMove): parent.save() @@ -223,7 +223,7 @@ class TestMPTT(TestCase): drawer.save() self.assertNotEqual(tree, drawer.tree_id) - + class TestSerialNumberExtraction(TestCase): """ Tests for serial number extraction code """ diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index c57e82addc..ab2ced7d5e 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -81,7 +81,7 @@ settings_urls = [ url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'), url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'), url(r'^i18n/?', include('django.conf.urls.i18n')), - + url(r'^global/?', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'), url(r'^report/?', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'), url(r'^category/?', SettingCategorySelectView.as_view(), name='settings-category'), @@ -137,7 +137,7 @@ urlpatterns = [ url(r'^login/?', auth_views.LoginView.as_view(), name='login'), url(r'^logout/', auth_views.LogoutView.as_view(template_name='registration/logged_out.html'), name='logout'), - + url(r'^settings/', include(settings_urls)), url(r'^edit-user/', EditUserView.as_view(), name='edit-user'), diff --git a/InvenTree/InvenTree/validators.py b/InvenTree/InvenTree/validators.py index f8199ef20b..622d1511ec 100644 --- a/InvenTree/InvenTree/validators.py +++ b/InvenTree/InvenTree/validators.py @@ -130,7 +130,7 @@ def validate_overage(value): if i < 0: raise ValidationError(_("Overage value must not be negative")) - + # Looks like an integer! return True except ValueError: diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index def4b34781..d285efae36 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -176,7 +176,7 @@ class InvenTreeRoleMixin(PermissionRequiredMixin): if role not in RuleSet.RULESET_NAMES: raise ValueError(f"Role '{role}' is not a valid role") - + if permission not in RuleSet.RULESET_PERMISSIONS: raise ValueError(f"Permission '{permission}' is not a valid permission") @@ -223,7 +223,7 @@ class InvenTreeRoleMixin(PermissionRequiredMixin): Return the 'permission_class' required for the current View. Must be one of: - + - view - change - add @@ -389,7 +389,7 @@ class QRCodeView(AjaxView): """ ajax_template_name = "qr_code.html" - + def get(self, request, *args, **kwargs): self.request = request self.pk = self.kwargs['pk'] @@ -398,7 +398,7 @@ class QRCodeView(AjaxView): def get_qr_data(self): """ Returns the text object to render to a QR code. The actual rendering will be handled by the template """ - + return None def get_context_data(self): @@ -406,7 +406,7 @@ class QRCodeView(AjaxView): Explicity passes the parameter 'qr_data' """ - + context = {} qr = self.get_qr_data() @@ -415,7 +415,7 @@ class QRCodeView(AjaxView): context['qr_data'] = qr else: context['error_msg'] = 'Error generating QR code' - + return context @@ -507,7 +507,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView): """ super(UpdateView, self).get(request, *args, **kwargs) - + return self.renderJsonResponse(request, self.get_form(), context=self.get_context_data()) def save(self, object, form, **kwargs): @@ -673,7 +673,7 @@ class SetPasswordView(AjaxUpdateView): p1 = request.POST.get('enter_password', '') p2 = request.POST.get('confirm_password', '') - + if valid: # Passwords must match @@ -712,7 +712,7 @@ class IndexView(TemplateView): # Generate a list of orderable parts which have stock below their minimum values # TODO - Is there a less expensive way to get these from the database # context['to_order'] = [part for part in Part.objects.filter(purchaseable=True) if part.need_to_restock()] - + # Generate a list of assembly parts which have stock below their minimum values # TODO - Is there a less expensive way to get these from the database # context['to_build'] = [part for part in Part.objects.filter(assembly=True) if part.need_to_restock()] @@ -752,7 +752,7 @@ class DynamicJsView(TemplateView): template_name = "" content_type = 'text/javascript' - + class SettingsView(TemplateView): """ View for configuring User settings @@ -830,7 +830,7 @@ class AppearanceSelectView(FormView): if form.is_valid(): theme_selected = form.cleaned_data['name'] - + # Set color theme to form selection user_theme.name = theme_selected user_theme.save() @@ -893,7 +893,7 @@ class DatabaseStatsView(AjaxView): # Part stats ctx['part_count'] = Part.objects.count() ctx['part_cat_count'] = PartCategory.objects.count() - + # Stock stats ctx['stock_item_count'] = StockItem.objects.count() ctx['stock_loc_count'] = StockLocation.objects.count() diff --git a/InvenTree/barcodes/api.py b/InvenTree/barcodes/api.py index e6b3ea84e3..6ab848c3f6 100644 --- a/InvenTree/barcodes/api.py +++ b/InvenTree/barcodes/api.py @@ -73,7 +73,7 @@ class BarcodeScan(APIView): # A plugin has been found! if plugin is not None: - + # Try to associate with a stock item item = plugin.getStockItem() @@ -133,7 +133,7 @@ class BarcodeScan(APIView): class BarcodeAssign(APIView): """ Endpoint for assigning a barcode to a stock item. - + - This only works if the barcode is not already associated with an object in the database - If the barcode does not match an object, then the barcode hash is assigned to the StockItem """ @@ -178,7 +178,7 @@ class BarcodeAssign(APIView): # Matching plugin was found if plugin is not None: - + hash = plugin.hash() response['hash'] = hash response['plugin'] = plugin.name @@ -234,7 +234,7 @@ class BarcodeAssign(APIView): barcode_api_urls = [ url(r'^link/$', BarcodeAssign.as_view(), name='api-barcode-link'), - + # Catch-all performs barcode 'scan' url(r'^.*$', BarcodeScan.as_view(), name='api-barcode-scan'), ] diff --git a/InvenTree/barcodes/barcode.py b/InvenTree/barcodes/barcode.py index a00e91d7e4..7ab9f3716a 100644 --- a/InvenTree/barcodes/barcode.py +++ b/InvenTree/barcodes/barcode.py @@ -21,7 +21,7 @@ def hash_barcode(barcode_data): HACK: Remove any 'non printable' characters from the hash, as it seems browers will remove special control characters... - + TODO: Work out a way around this! """ diff --git a/InvenTree/barcodes/tests.py b/InvenTree/barcodes/tests.py index 5f178d923c..1d8f53ec4c 100644 --- a/InvenTree/barcodes/tests.py +++ b/InvenTree/barcodes/tests.py @@ -92,7 +92,7 @@ class BarcodeAPITest(APITestCase): data = response.data self.assertEqual(response.status_code, status.HTTP_200_OK) - + self.assertIn('stockitem', data) pk = data['stockitem']['pk'] @@ -121,7 +121,7 @@ class BarcodeAPITest(APITestCase): data = response.data self.assertEqual(response.status_code, status.HTTP_200_OK) - + self.assertIn('success', data) hash = data['hash'] diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index 10cc7e2024..160642281a 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -20,7 +20,7 @@ from .serializers import BuildSerializer, BuildItemSerializer class BuildList(generics.ListCreateAPIView): """ API endpoint for accessing a list of Build objects. - + - GET: Return list of objects (with filters) - POST: Create a new Build object """ @@ -65,7 +65,7 @@ class BuildList(generics.ListCreateAPIView): queryset = BuildSerializer.annotate_queryset(queryset) return queryset - + def filter_queryset(self, queryset): queryset = super().filter_queryset(queryset) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index c5da505f43..a278b4e17c 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -118,7 +118,7 @@ class Build(MPTTModel): def get_absolute_url(self): return reverse('build-detail', kwargs={'pk': self.id}) - + reference = models.CharField( unique=True, max_length=64, @@ -168,7 +168,7 @@ class Build(MPTTModel): null=True, blank=True, help_text=_('SalesOrder to which this build is allocated') ) - + take_from = models.ForeignKey( 'stock.StockLocation', verbose_name=_('Source Location'), @@ -177,7 +177,7 @@ class Build(MPTTModel): null=True, blank=True, help_text=_('Select location to take stock from for this build (leave blank to take from any stock location)') ) - + destination = models.ForeignKey( 'stock.StockLocation', verbose_name=_('Destination Location'), @@ -207,7 +207,7 @@ class Build(MPTTModel): validators=[MinValueValidator(0)], help_text=_('Build status code') ) - + batch = models.CharField( verbose_name=_('Batch Code'), max_length=100, @@ -215,9 +215,9 @@ class Build(MPTTModel): null=True, help_text=_('Batch code for this build output') ) - + creation_date = models.DateField(auto_now_add=True, editable=False, verbose_name=_('Creation Date')) - + target_date = models.DateField( null=True, blank=True, verbose_name=_('Target completion date'), @@ -251,7 +251,7 @@ class Build(MPTTModel): help_text=_('User responsible for this build order'), related_name='builds_responsible', ) - + link = InvenTree.fields.InvenTreeURLField( verbose_name=_('External Link'), blank=True, help_text=_('Link to external URL') @@ -272,7 +272,7 @@ class Build(MPTTModel): else: descendants = self.get_descendants(include_self=True) Build.objects.filter(parent__pk__in=[d.pk for d in descendants]) - + def sub_build_count(self, cascade=True): """ Return the number of sub builds under this one. @@ -295,7 +295,7 @@ class Build(MPTTModel): query = query.filter(Build.OVERDUE_FILTER) return query.exists() - + @property def active(self): """ @@ -441,7 +441,7 @@ class Build(MPTTModel): # Extract the "most recent" build order reference builds = cls.objects.exclude(reference=None) - + if not builds.exists(): return None @@ -543,7 +543,7 @@ class Build(MPTTModel): - The sub_item in the BOM line must *not* be trackable - There is only a single stock item available (which has not already been allocated to this build) - The stock item has an availability greater than zero - + Returns: A list object containing the StockItem objects to be allocated (and the quantities). Each item in the list is a dict as follows: @@ -648,7 +648,7 @@ class Build(MPTTModel): """ Deletes all stock allocations for this build. """ - + allocations = BuildItem.objects.filter(build=self) allocations.delete() @@ -1145,7 +1145,7 @@ class BuildItem(models.Model): """ self.validate_unique() - + super().clean() errors = {} @@ -1159,7 +1159,7 @@ class BuildItem(models.Model): # Allocated part must be in the BOM for the master part if self.stock_item.part not in self.build.part.getRequiredParts(recursive=False): errors['stock_item'] = [_("Selected stock item not found in BOM for part '{p}'").format(p=self.build.part.full_name)] - + # Allocated quantity cannot exceed available stock quantity if self.quantity > self.stock_item.quantity: errors['quantity'] = [_("Allocated quantity ({n}) must not exceed available quantity ({q})").format( diff --git a/InvenTree/build/test_api.py b/InvenTree/build/test_api.py index 02bcde6bb4..a1d0c3df9f 100644 --- a/InvenTree/build/test_api.py +++ b/InvenTree/build/test_api.py @@ -30,7 +30,7 @@ class BuildAPITest(InvenTreeAPITestCase): 'build.change', 'build.add' ] - + def setUp(self): super().setUp() @@ -54,7 +54,7 @@ class BuildListTest(BuildAPITest): builds = self.get(self.url, data={'active': True}) self.assertEqual(len(builds.data), 1) - + builds = self.get(self.url, data={'status': BuildStatus.COMPLETE}) self.assertEqual(len(builds.data), 4) diff --git a/InvenTree/build/test_build.py b/InvenTree/build/test_build.py index 0beab60d52..a3b69646dd 100644 --- a/InvenTree/build/test_build.py +++ b/InvenTree/build/test_build.py @@ -114,7 +114,7 @@ class BuildTest(TestCase): # Perform some basic tests before we start the ball rolling self.assertEqual(StockItem.objects.count(), 6) - + # Build is PENDING self.assertEqual(self.build.status, status.BuildStatus.PENDING) @@ -142,7 +142,7 @@ class BuildTest(TestCase): # Create a BuiltItem which points to an invalid StockItem b = BuildItem(stock_item=stock, build=self.build, quantity=10) - + with self.assertRaises(ValidationError): b.save() @@ -339,7 +339,7 @@ class BuildTest(TestCase): self.assertTrue(self.build.can_complete) self.build.complete_build(None) - + self.assertEqual(self.build.status, status.BuildStatus.COMPLETE) # the original BuildItem objects should have been deleted! @@ -351,12 +351,12 @@ class BuildTest(TestCase): # This stock item has been depleted! with self.assertRaises(StockItem.DoesNotExist): StockItem.objects.get(pk=self.stock_1_1.pk) - + # This stock item has *not* been depleted x = StockItem.objects.get(pk=self.stock_2_1.pk) self.assertEqual(x.quantity, 4970) - + # And 10 new stock items created for the build output outputs = StockItem.objects.filter(build=self.build) diff --git a/InvenTree/build/tests.py b/InvenTree/build/tests.py index e16ef9a282..9a440e0b93 100644 --- a/InvenTree/build/tests.py +++ b/InvenTree/build/tests.py @@ -251,7 +251,7 @@ class TestBuildViews(TestCase): content = str(response.content) self.assertIn(build.title, content) - + def test_build_create(self): """ Test the build creation view (ajax form) """ @@ -260,7 +260,7 @@ class TestBuildViews(TestCase): # Create build without specifying part response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + # Create build with valid part response = self.client.get(url, {'part': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) @@ -281,7 +281,7 @@ class TestBuildViews(TestCase): # Get the page in editing mode response = self.client.get(url, {'edit': 1}) self.assertEqual(response.status_code, 200) - + def test_build_item_create(self): """ Test the BuildItem creation view (ajax form) """ @@ -305,7 +305,7 @@ class TestBuildViews(TestCase): def test_build_item_edit(self): """ Test the BuildItem edit view (ajax form) """ - + # TODO # url = reverse('build-item-edit') pass @@ -323,7 +323,7 @@ class TestBuildViews(TestCase): # Test without confirmation response = self.client.post(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + data = json.loads(response.content) self.assertFalse(data['form_valid']) @@ -353,7 +353,7 @@ class TestBuildViews(TestCase): # Test with confirmation, invalid location response = self.client.post(url, {'confirm': 1, 'location': 9999}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + data = json.loads(response.content) self.assertFalse(data['form_valid']) @@ -365,7 +365,7 @@ class TestBuildViews(TestCase): # Test without confirmation response = self.client.post(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + data = json.loads(response.content) self.assertFalse(data['form_valid']) @@ -393,7 +393,7 @@ class TestBuildViews(TestCase): data = json.loads(response.content) self.assertFalse(data['form_valid']) - + # Test with confirmation response = self.client.post(url, {'confirm': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 66815cae70..6e72f7f3e6 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -159,7 +159,7 @@ class BuildOutputCreate(AjaxUpdateView): if quantity: build = self.get_object() - + # Check that requested output don't exceed build remaining quantity maximum_output = int(build.remaining - build.incomplete_count) if quantity > maximum_output: @@ -318,7 +318,7 @@ class BuildUnallocate(AjaxUpdateView): form_class = forms.UnallocateBuildForm ajax_form_title = _("Unallocate Stock") ajax_template_name = "build/unallocate.html" - + def get_initial(self): initials = super().get_initial() @@ -341,7 +341,7 @@ class BuildUnallocate(AjaxUpdateView): build = self.get_object() form = self.get_form() - + confirm = request.POST.get('confirm', False) output_id = request.POST.get('output_id', None) @@ -382,7 +382,7 @@ class BuildUnallocate(AjaxUpdateView): # Unallocate "untracked" parts else: build.unallocateUntracked(part=part) - + data = { 'form_valid': valid, } @@ -401,7 +401,7 @@ class BuildComplete(AjaxUpdateView): model = Build form_class = forms.CompleteBuildForm - + ajax_form_title = _('Complete Build Order') ajax_template_name = 'build/complete.html' @@ -437,9 +437,9 @@ class BuildOutputComplete(AjaxUpdateView): context_object_name = "build" ajax_form_title = _("Complete Build Output") ajax_template_name = "build/complete_output.html" - + def get_form(self): - + build = self.get_object() form = super().get_form() @@ -500,7 +500,7 @@ class BuildOutputComplete(AjaxUpdateView): - If the part being built has a default location, pre-select that location """ - + initials = super().get_initial() build = self.get_object() @@ -585,7 +585,7 @@ class BuildOutputComplete(AjaxUpdateView): location=location, status=stock_status, ) - + def get_data(self): """ Provide feedback data back to the form """ return { @@ -600,7 +600,7 @@ class BuildNotes(InvenTreeRoleMixin, UpdateView): context_object_name = 'build' template_name = 'build/notes.html' model = Build - + # Override the default permission role for this View role_required = 'build.view' @@ -612,7 +612,7 @@ class BuildNotes(InvenTreeRoleMixin, UpdateView): def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) - + ctx['editing'] = str2bool(self.request.GET.get('edit', '')) return ctx @@ -746,7 +746,7 @@ class BuildCreate(AjaxCreateView): class BuildUpdate(AjaxUpdateView): """ View for editing a Build object """ - + model = Build form_class = forms.EditBuildForm context_object_name = 'build' @@ -804,7 +804,7 @@ class BuildItemDelete(AjaxDeleteView): ajax_template_name = 'build/delete_build_item.html' ajax_form_title = _('Unallocate Stock') context_object_name = 'item' - + def get_data(self): return { 'danger': _('Removed parts from build allocation') @@ -826,7 +826,7 @@ class BuildItemCreate(AjaxCreateView): # The "part" which is being allocated to the output part = None - + available_stock = None def get_context_data(self): @@ -906,7 +906,7 @@ class BuildItemCreate(AjaxCreateView): if part_id: try: self.part = Part.objects.get(pk=part_id) - + except (ValueError, Part.DoesNotExist): pass @@ -958,7 +958,7 @@ class BuildItemCreate(AjaxCreateView): # Reference to a StockItem object item = None - + # Reference to a Build object build = None @@ -999,7 +999,7 @@ class BuildItemCreate(AjaxCreateView): quantity = float(quantity) elif required_quantity is not None: quantity = required_quantity - + item_id = self.get_param('item') # If the request specifies a particular StockItem @@ -1035,7 +1035,7 @@ class BuildItemEdit(AjaxUpdateView): ajax_template_name = 'build/edit_build_item.html' form_class = forms.EditBuildItemForm ajax_form_title = _('Edit Stock Allocation') - + def get_data(self): return { 'info': _('Updated Build Item'), @@ -1068,7 +1068,7 @@ class BuildAttachmentCreate(AjaxCreateView): model = BuildOrderAttachment form_class = forms.EditBuildAttachmentForm ajax_form_title = _('Add Build Order Attachment') - + def save(self, form, **kwargs): """ Add information on the user that uploaded the attachment @@ -1105,7 +1105,7 @@ class BuildAttachmentCreate(AjaxCreateView): form = super().get_form() form.fields['build'].widget = HiddenInput() - + return form diff --git a/InvenTree/common/admin.py b/InvenTree/common/admin.py index 3edcd1fa8d..c2da1ddd63 100644 --- a/InvenTree/common/admin.py +++ b/InvenTree/common/admin.py @@ -9,7 +9,7 @@ from .models import InvenTreeSetting class SettingsAdmin(ImportExportModelAdmin): - + list_display = ('key', 'value') diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index bc2ca4214b..356e58e8e9 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -40,7 +40,7 @@ class InvenTreeSetting(models.Model): The key of each item is the name of the value as it appears in the database. Each global setting has the following parameters: - + - name: Translatable string name of the setting (required) - description: Translatable string description of the setting (required) - default: Default value (optional) @@ -412,7 +412,7 @@ class InvenTreeSetting(models.Model): # Evaluate the function (we expect it will return a list of tuples...) return choices() """ - + return choices @classmethod @@ -522,7 +522,7 @@ class InvenTreeSetting(models.Model): # Enforce standard boolean representation if setting.is_bool(): value = InvenTree.helpers.str2bool(value) - + setting.value = str(value) setting.save() @@ -664,7 +664,7 @@ class InvenTreeSetting(models.Model): if validator == int: return True - + if type(validator) in [list, tuple]: for v in validator: if v == int: @@ -675,7 +675,7 @@ class InvenTreeSetting(models.Model): def as_int(self): """ Return the value of this setting converted to a boolean value. - + If an error occurs, return the default value """ @@ -685,7 +685,7 @@ class InvenTreeSetting(models.Model): value = self.default_value() return value - + class PriceBreak(models.Model): """ diff --git a/InvenTree/common/settings.py b/InvenTree/common/settings.py index 134d3f3f7c..4d98bc495b 100644 --- a/InvenTree/common/settings.py +++ b/InvenTree/common/settings.py @@ -19,7 +19,7 @@ def currency_code_default(): if code not in CURRENCIES: code = 'USD' - + return code diff --git a/InvenTree/common/test_views.py b/InvenTree/common/test_views.py index 0cd902d083..8dc5830108 100644 --- a/InvenTree/common/test_views.py +++ b/InvenTree/common/test_views.py @@ -117,7 +117,7 @@ class SettingsViewTest(TestCase): """ Test for binary value """ - + setting = InvenTreeSetting.get_setting_object('PART_COMPONENT') self.assertTrue(setting.as_bool()) diff --git a/InvenTree/common/tests.py b/InvenTree/common/tests.py index d8777785f9..d20f76baa0 100644 --- a/InvenTree/common/tests.py +++ b/InvenTree/common/tests.py @@ -19,7 +19,7 @@ class SettingsTest(TestCase): def setUp(self): user = get_user_model() - + self.user = user.objects.create_user('username', 'user@email.com', 'password') self.user.is_staff = True self.user.save() diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 31d11e30cc..8cc344c9ab 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -48,7 +48,7 @@ class SettingEdit(AjaxUpdateView): """ form = super().get_form() - + setting = self.get_object() choices = setting.choices() diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index 494b3652b2..ff8b6d667b 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -41,7 +41,7 @@ class CompanyList(generics.ListCreateAPIView): queryset = CompanySerializer.annotate_queryset(queryset) return queryset - + filter_backends = [ DjangoFilterBackend, filters.SearchFilter, @@ -116,7 +116,7 @@ class ManufacturerPartList(generics.ListCreateAPIView): kwargs['pretty'] = str2bool(self.request.query_params.get('pretty', None)) except AttributeError: pass - + kwargs['context'] = self.get_serializer_context() return self.serializer_class(*args, **kwargs) @@ -167,7 +167,7 @@ class ManufacturerPartList(generics.ListCreateAPIView): 'part__name', 'part__description', ] - + class ManufacturerPartDetail(generics.RetrieveUpdateDestroyAPIView): """ API endpoint for detail view of ManufacturerPart object @@ -255,7 +255,7 @@ class SupplierPartList(generics.ListCreateAPIView): kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', None)) except AttributeError: pass - + try: kwargs['supplier_detail'] = str2bool(self.request.query_params.get('supplier_detail', None)) except AttributeError: @@ -270,7 +270,7 @@ class SupplierPartList(generics.ListCreateAPIView): kwargs['pretty'] = str2bool(self.request.query_params.get('pretty', None)) except AttributeError: pass - + kwargs['context'] = self.get_serializer_context() return self.serializer_class(*args, **kwargs) diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index 8ad8c6bfea..62a46fcd6f 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -158,7 +158,7 @@ class EditSupplierPartForm(HelperForm): empty_choice = [('', '----------')] manufacturers = [(manufacturer.id, manufacturer.name) for manufacturer in Company.objects.filter(is_manufacturer=True)] - + return empty_choice + manufacturers def __init__(self, *args, **kwargs): diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 89a3f6c9bf..8b6a45556e 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -152,7 +152,7 @@ class Company(models.Model): def currency_code(self): """ Return the currency code associated with this company. - + - If the currency code is invalid, use the default currency - If the currency code is not specified, use the default currency """ @@ -187,7 +187,7 @@ class Company(models.Model): return getMediaUrl(self.image.thumbnail.url) else: return getBlankThumbnail() - + @property def manufactured_part_count(self): """ The number of parts manufactured by this company """ @@ -302,7 +302,7 @@ class ManufacturerPart(models.Model): class Meta: unique_together = ('part', 'manufacturer', 'MPN') - + part = models.ForeignKey('part.Part', on_delete=models.CASCADE, related_name='manufacturer_parts', verbose_name=_('Base Part'), @@ -311,7 +311,7 @@ class ManufacturerPart(models.Model): }, help_text=_('Select part'), ) - + manufacturer = models.ForeignKey( Company, on_delete=models.CASCADE, @@ -359,7 +359,7 @@ class ManufacturerPart(models.Model): if not manufacturer_part: manufacturer_part = ManufacturerPart(part=part, manufacturer=manufacturer, MPN=mpn, description=description, link=link) manufacturer_part.save() - + return manufacturer_part def __str__(self): @@ -414,7 +414,7 @@ class SupplierPart(models.Model): MPN = kwargs.pop('MPN') else: MPN = None - + if manufacturer or MPN: if not self.manufacturer_part: # Create ManufacturerPart @@ -429,7 +429,7 @@ class SupplierPart(models.Model): manufacturer_part_id = self.manufacturer_part.id except AttributeError: manufacturer_part_id = None - + if manufacturer_part_id: try: (manufacturer_part, created) = ManufacturerPart.objects.update_or_create(part=self.part, @@ -504,7 +504,7 @@ class SupplierPart(models.Model): base_cost = models.DecimalField(max_digits=10, decimal_places=3, default=0, validators=[MinValueValidator(0)], verbose_name=_('base cost'), help_text=_('Minimum charge (e.g. stocking fee)')) packaging = models.CharField(max_length=50, blank=True, null=True, verbose_name=_('Packaging'), help_text=_('Part packaging')) - + multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], verbose_name=_('multiple'), help_text=_('Order multiple')) # TODO - Reimplement lead-time as a charfield with special validation (pattern matching). @@ -613,7 +613,7 @@ class SupplierPart(models.Model): pb_cost = pb_min.convert_to(currency) # Trigger cost calculation using smallest price break pb_found = True - + # Convert quantity to decimal.Decimal format quantity = decimal.Decimal(f'{quantity}') @@ -669,7 +669,7 @@ class SupplierPart(models.Model): if self.manufacturer_string: s = s + ' | ' + self.manufacturer_string - + return s diff --git a/InvenTree/company/serializers.py b/InvenTree/company/serializers.py index 335a351583..4b1019656e 100644 --- a/InvenTree/company/serializers.py +++ b/InvenTree/company/serializers.py @@ -51,7 +51,7 @@ class CompanySerializer(InvenTreeModelSerializer): return queryset url = serializers.CharField(source='get_absolute_url', read_only=True) - + image = serializers.CharField(source='get_thumbnail_url', read_only=True) parts_supplied = serializers.IntegerField(read_only=True) @@ -157,9 +157,9 @@ class SupplierPartSerializer(InvenTreeModelSerializer): self.fields.pop('pretty_name') supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True)) - + manufacturer = serializers.PrimaryKeyRelatedField(source='manufacturer_part.manufacturer', read_only=True) - + MPN = serializers.StringRelatedField(source='manufacturer_part.MPN') manufacturer_part = ManufacturerPartSerializer(read_only=True) diff --git a/InvenTree/company/test_migrations.py b/InvenTree/company/test_migrations.py index bf6e212f7a..882d54260f 100644 --- a/InvenTree/company/test_migrations.py +++ b/InvenTree/company/test_migrations.py @@ -48,7 +48,7 @@ class TestManufacturerField(MigratorTestCase): - Company object (supplier) - SupplierPart object """ - + Part = self.old_state.apps.get_model('part', 'part') Company = self.old_state.apps.get_model('company', 'company') SupplierPart = self.old_state.apps.get_model('company', 'supplierpart') @@ -123,7 +123,7 @@ class TestManufacturerPart(MigratorTestCase): - Company object (supplier) - SupplierPart object """ - + Part = self.old_state.apps.get_model('part', 'part') Company = self.old_state.apps.get_model('company', 'company') SupplierPart = self.old_state.apps.get_model('company', 'supplierpart') @@ -220,7 +220,7 @@ class TestManufacturerPart(MigratorTestCase): # Check on the SupplierPart objects SupplierPart = self.new_state.apps.get_model('company', 'supplierpart') - + supplier_parts = SupplierPart.objects.all() self.assertEqual(supplier_parts.count(), 6) @@ -229,10 +229,10 @@ class TestManufacturerPart(MigratorTestCase): # Check on the ManufacturerPart objects ManufacturerPart = self.new_state.apps.get_model('company', 'manufacturerpart') - + manufacturer_parts = ManufacturerPart.objects.all() self.assertEqual(manufacturer_parts.count(), 4) - + manufacturer_part = manufacturer_parts.first() self.assertEqual(manufacturer_part.MPN, 'MUR-CAP-123456') @@ -293,7 +293,7 @@ class TestCurrencyMigration(MigratorTestCase): self.assertIsNone(pb.price) def test_currency_migration(self): - + PB = self.new_state.apps.get_model('company', 'supplierpricebreak') for pb in PB.objects.all(): diff --git a/InvenTree/company/test_views.py b/InvenTree/company/test_views.py index e6eb54e0bf..cdb2d32af9 100644 --- a/InvenTree/company/test_views.py +++ b/InvenTree/company/test_views.py @@ -30,7 +30,7 @@ class CompanyViewTestBase(TestCase): # Create a user user = get_user_model() - + self.user = user.objects.create_user( username='username', email='user@email.com', @@ -83,7 +83,7 @@ class SupplierPartViewTests(CompanyViewTestBase): def test_supplier_part_create(self): """ Test the SupplierPartCreate view. - + This view allows some additional functionality, specifically it allows the user to create a single-quantity price break automatically, when saving the new SupplierPart model. @@ -171,7 +171,7 @@ class SupplierPartViewTests(CompanyViewTestBase): 'confirm_delete': True }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - + self.assertEqual(response.status_code, 200) self.assertEqual(n - 2, SupplierPart.objects.count()) @@ -213,7 +213,7 @@ class ManufacturerPartViewTests(CompanyViewTestBase): """ Test the ManufacturerPartCreate view. """ - + url = reverse('manufacturer-part-create') # First check that we can GET the form @@ -252,7 +252,7 @@ class ManufacturerPartViewTests(CompanyViewTestBase): """ Test that the SupplierPartCreate view creates Manufacturer Part. """ - + url = reverse('supplier-part-create') # First check that we can GET the form @@ -297,7 +297,7 @@ class ManufacturerPartViewTests(CompanyViewTestBase): 'confirm_delete': True }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - + self.assertEqual(response.status_code, 200) # Check that the ManufacturerPart was deleted diff --git a/InvenTree/company/tests.py b/InvenTree/company/tests.py index ec56503815..5dd3bf81ab 100644 --- a/InvenTree/company/tests.py +++ b/InvenTree/company/tests.py @@ -71,7 +71,7 @@ class CompanySimpleTest(TestCase): acme = Company.objects.get(pk=1) appel = Company.objects.get(pk=2) zerg = Company.objects.get(pk=3) - + self.assertTrue(acme.has_parts) self.assertEqual(acme.supplied_part_count, 4) @@ -82,7 +82,7 @@ class CompanySimpleTest(TestCase): self.assertEqual(zerg.supplied_part_count, 2) def test_price_breaks(self): - + self.assertTrue(self.acme0001.has_price_breaks) self.assertTrue(self.acme0002.has_price_breaks) self.assertTrue(self.zergm312.has_price_breaks) @@ -121,7 +121,7 @@ class CompanySimpleTest(TestCase): pmin, pmax = m2x4.get_price_range(5) self.assertEqual(pmin, 35) self.assertEqual(pmax, 37.5) - + m3x12 = Part.objects.get(name='M3x12 SHCS') self.assertEqual(m3x12.get_price_info(0.3), Decimal('2.4')) @@ -187,14 +187,14 @@ class ManufacturerPartSimpleTest(TestCase): # Create a manufacturer part self.part = Part.objects.get(pk=1) manufacturer = Company.objects.get(pk=1) - + self.mp = ManufacturerPart.create( part=self.part, manufacturer=manufacturer, mpn='PART_NUMBER', description='THIS IS A MANUFACTURER PART', ) - + # Create a supplier part supplier = Company.objects.get(pk=5) supplier_part = SupplierPart.objects.create( diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index b87b0626ae..11f1be5339 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -55,7 +55,7 @@ price_break_urls = [ manufacturer_part_detail_urls = [ url(r'^edit/?', views.ManufacturerPartEdit.as_view(), name='manufacturer-part-edit'), - + url(r'^suppliers/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-suppliers'), url('^.*$', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part_suppliers.html'), name='manufacturer-part-detail'), diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index be7d326c36..120832a31c 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -96,7 +96,7 @@ class CompanyIndex(InvenTreeRoleMixin, ListView): if self.request.path == item: context = lookup[item] break - + if context is None: context = default @@ -279,7 +279,7 @@ class CompanyCreate(AjaxCreateView): if url == reverse('supplier-create'): return _("Create new Supplier") - + if url == reverse('manufacturer-create'): return _('Create new Manufacturer') @@ -298,7 +298,7 @@ class CompanyCreate(AjaxCreateView): initials['is_supplier'] = True initials['is_customer'] = False initials['is_manufacturer'] = False - + elif url == reverse('manufacturer-create'): initials['is_manufacturer'] = True initials['is_supplier'] = True @@ -319,7 +319,7 @@ class CompanyCreate(AjaxCreateView): class CompanyDelete(AjaxDeleteView): """ View for deleting a Company object """ - + model = Company success_url = '/company/' ajax_template_name = 'company/delete.html' @@ -415,7 +415,7 @@ class ManufacturerPartCreate(AjaxCreateView): initials['manufacturer'] = Company.objects.get(pk=manufacturer_id) except (ValueError, Company.DoesNotExist): pass - + if part_id: try: initials['part'] = Part.objects.get(pk=part_id) @@ -427,7 +427,7 @@ class ManufacturerPartCreate(AjaxCreateView): class ManufacturerPartDelete(AjaxDeleteView): """ Delete view for removing a ManufacturerPart. - + ManufacturerParts can be deleted using a variety of 'selectors'. - ?part= -> Delete a single ManufacturerPart object @@ -561,7 +561,7 @@ class SupplierPartEdit(AjaxUpdateView): initials = super(SupplierPartEdit, self).get_initial().copy() supplier_part = self.get_object() - + if supplier_part.manufacturer_part: initials['manufacturer'] = supplier_part.manufacturer_part.manufacturer.id initials['MPN'] = supplier_part.manufacturer_part.MPN @@ -686,7 +686,7 @@ class SupplierPartCreate(AjaxCreateView): initials['MPN'] = manufacturer_part_obj.MPN except (ValueError, ManufacturerPart.DoesNotExist, Part.DoesNotExist, Company.DoesNotExist): pass - + if part_id: try: initials['part'] = Part.objects.get(pk=part_id) @@ -703,13 +703,13 @@ class SupplierPartCreate(AjaxCreateView): if currency_code: initials['single_pricing'] = ('', currency) - + return initials class SupplierPartDelete(AjaxDeleteView): """ Delete view for removing a SupplierPart. - + SupplierParts can be deleted using a variety of 'selectors'. - ?part= -> Delete a single SupplierPart object @@ -840,7 +840,7 @@ class PriceBreakCreate(AjaxCreateView): # Extract the currency object associated with the code currency = CURRENCIES.get(currency_code, None) - + if currency: initials['price'] = [1.0, currency] diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index 0d0d71b50d..fc082e4a50 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -159,7 +159,7 @@ class StockItemLabelList(LabelListView, StockItemLabelMixin): """ Filter the StockItem label queryset. """ - + queryset = super().filter_queryset(queryset) # List of StockItem objects to match against @@ -178,7 +178,7 @@ class StockItemLabelList(LabelListView, StockItemLabelMixin): # Keep track of which labels match every specified stockitem valid_label_ids = set() - + for label in queryset.all(): matches = True @@ -293,7 +293,7 @@ class StockLocationLabelList(LabelListView, StockLocationLabelMixin): """ queryset = super().filter_queryset(queryset) - + # List of StockLocation objects to match against locations = self.get_locations() diff --git a/InvenTree/label/apps.py b/InvenTree/label/apps.py index 2b99921703..e51767d5f0 100644 --- a/InvenTree/label/apps.py +++ b/InvenTree/label/apps.py @@ -139,7 +139,7 @@ class LabelConfig(AppConfig): except: # Database might not yet be ready return - + src_dir = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'templates', diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index 5c1b104670..71ccc73ac9 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -44,7 +44,7 @@ def rename_label(instance, filename): def validate_stock_item_filters(filters): - + filters = validateFilterString(filters, model=stock.models.StockItem) return filters @@ -82,7 +82,7 @@ class LabelTemplate(models.Model): # Each class of label files will be stored in a separate subdirectory SUBDIR = "label" - + # Object we will be printing against (will be filled out later) object_to_print = None diff --git a/InvenTree/label/test_api.py b/InvenTree/label/test_api.py index 92e7733891..af4c0782ec 100644 --- a/InvenTree/label/test_api.py +++ b/InvenTree/label/test_api.py @@ -40,7 +40,7 @@ class TestReportTests(InvenTreeAPITestCase): return response.data def test_list(self): - + response = self.do_list() # TODO - Add some report templates to the fixtures diff --git a/InvenTree/order/forms.py b/InvenTree/order/forms.py index 4c9caf3b53..e7336f5b0d 100644 --- a/InvenTree/order/forms.py +++ b/InvenTree/order/forms.py @@ -64,7 +64,7 @@ class CancelSalesOrderForm(HelperForm): fields = [ 'confirm', ] - + class ShipSalesOrderForm(HelperForm): diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index d3b09dec1e..97e69cf562 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -309,7 +309,7 @@ class PurchaseOrder(Order): """ A PurchaseOrder can only be cancelled under the following circumstances: """ - + return self.status in [ PurchaseOrderStatus.PLACED, PurchaseOrderStatus.PENDING @@ -378,7 +378,7 @@ class PurchaseOrder(Order): # Has this order been completed? if len(self.pending_line_items()) == 0: - + self.received_by = user self.complete_order() # This will save the model @@ -419,7 +419,7 @@ class SalesOrder(Order): except (ValueError, TypeError): # Date processing error, return queryset unchanged return queryset - + # Construct a queryset for "completed" orders within the range completed = Q(status__in=SalesOrderStatus.COMPLETE) & Q(shipment_date__gte=min_date) & Q(shipment_date__lte=max_date) @@ -495,7 +495,7 @@ class SalesOrder(Order): for line in self.lines.all(): if not line.is_fully_allocated(): return False - + return True def is_over_allocated(self): @@ -590,11 +590,11 @@ class SalesOrderAttachment(InvenTreeAttachment): class OrderLineItem(models.Model): """ Abstract model for an order line item - + Attributes: quantity: Number of items note: Annotation for the item - + """ class Meta: @@ -603,13 +603,13 @@ class OrderLineItem(models.Model): quantity = RoundingDecimalField(max_digits=15, decimal_places=5, validators=[MinValueValidator(0)], default=1, verbose_name=_('Quantity'), help_text=_('Item quantity')) reference = models.CharField(max_length=100, blank=True, verbose_name=_('Reference'), help_text=_('Line item reference')) - + notes = models.CharField(max_length=500, blank=True, verbose_name=_('Notes'), help_text=_('Line item notes')) class PurchaseOrderLineItem(OrderLineItem): """ Model for a purchase order line item. - + Attributes: order: Reference to a PurchaseOrder object @@ -637,7 +637,7 @@ class PurchaseOrderLineItem(OrderLineItem): def get_base_part(self): """ Return the base-part for the line item """ return self.part.part - + # TODO - Function callback for when the SupplierPart is deleted? part = models.ForeignKey( diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index a04798c303..cd2dca828f 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -61,7 +61,7 @@ class POSerializer(InvenTreeModelSerializer): return queryset supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True) - + line_items = serializers.IntegerField(read_only=True) status_text = serializers.CharField(source='get_status_display', read_only=True) @@ -70,7 +70,7 @@ class POSerializer(InvenTreeModelSerializer): class Meta: model = PurchaseOrder - + fields = [ 'pk', 'issue_date', @@ -89,7 +89,7 @@ class POSerializer(InvenTreeModelSerializer): 'target_date', 'notes', ] - + read_only_fields = [ 'reference', 'status' @@ -110,10 +110,10 @@ class POLineItemSerializer(InvenTreeModelSerializer): quantity = serializers.FloatField() received = serializers.FloatField() - + part_detail = PartBriefSerializer(source='get_base_part', many=False, read_only=True) supplier_part_detail = SupplierPartSerializer(source='part', many=False, read_only=True) - + purchase_price_string = serializers.CharField(source='purchase_price', read_only=True) class Meta: @@ -144,7 +144,7 @@ class POAttachmentSerializer(InvenTreeModelSerializer): class Meta: model = PurchaseOrderAttachment - + fields = [ 'pk', 'order', @@ -270,7 +270,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer): if allocations is not True: self.fields.pop('allocations') - + order_detail = SalesOrderSerializer(source='order', many=False, read_only=True) part_detail = PartBriefSerializer(source='part', many=False, read_only=True) allocations = SalesOrderAllocationSerializer(many=True, read_only=True) @@ -306,7 +306,7 @@ class SOAttachmentSerializer(InvenTreeModelSerializer): class Meta: model = SalesOrderAttachment - + fields = [ 'pk', 'order', diff --git a/InvenTree/order/test_api.py b/InvenTree/order/test_api.py index cb92b8b384..0ef63e485a 100644 --- a/InvenTree/order/test_api.py +++ b/InvenTree/order/test_api.py @@ -94,7 +94,7 @@ class PurchaseOrderTest(OrderTest): url = '/api/order/po/1/' response = self.get(url) - + self.assertEqual(response.status_code, 200) data = response.data @@ -109,7 +109,7 @@ class PurchaseOrderTest(OrderTest): response = self.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) - + class SalesOrderTest(OrderTest): """ diff --git a/InvenTree/order/test_sales_order.py b/InvenTree/order/test_sales_order.py index 0b37b96409..8337ff4b57 100644 --- a/InvenTree/order/test_sales_order.py +++ b/InvenTree/order/test_sales_order.py @@ -73,7 +73,7 @@ class SalesOrderTest(TestCase): def test_add_duplicate_line_item(self): # Adding a duplicate line item to a SalesOrder is accepted - + for ii in range(1, 5): SalesOrderLineItem.objects.create(order=self.order, part=self.part, quantity=ii) @@ -107,7 +107,7 @@ class SalesOrderTest(TestCase): self.assertTrue(self.order.is_fully_allocated()) self.assertTrue(self.line.is_fully_allocated()) self.assertEqual(self.line.allocated_quantity(), 50) - + def test_order_cancel(self): # Allocate line items then cancel the order @@ -154,7 +154,7 @@ class SalesOrderTest(TestCase): for item in outputs.all(): self.assertEqual(item.quantity, 25) - + self.assertEqual(sa.sales_order, None) self.assertEqual(sb.sales_order, None) @@ -162,7 +162,7 @@ class SalesOrderTest(TestCase): self.assertEqual(SalesOrderAllocation.objects.count(), 0) self.assertEqual(self.order.status, status.SalesOrderStatus.SHIPPED) - + self.assertTrue(self.order.is_fully_allocated()) self.assertTrue(self.line.is_fully_allocated()) self.assertEqual(self.line.fulfilled_quantity(), 50) diff --git a/InvenTree/order/test_views.py b/InvenTree/order/test_views.py index 51981af105..23122d079d 100644 --- a/InvenTree/order/test_views.py +++ b/InvenTree/order/test_views.py @@ -17,7 +17,7 @@ import json class OrderViewTestCase(TestCase): - + fixtures = [ 'category', 'part', @@ -193,7 +193,7 @@ class POTests(OrderViewTestCase): # Test without confirmation response = self.client.post(url, {'confirm': 0}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + data = json.loads(response.content) self.assertFalse(data['form_valid']) @@ -221,7 +221,7 @@ class POTests(OrderViewTestCase): # GET the form (pass the correct info) response = self.client.get(url, {'order': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - + post_data = { 'part': 100, 'quantity': 45, @@ -303,7 +303,7 @@ class TestPOReceive(OrderViewTestCase): self.client.get(self.url, data, HTTP_X_REQUESTED_WITH='XMLHttpRequest') def test_receive_lines(self): - + post_data = { } @@ -330,7 +330,7 @@ class TestPOReceive(OrderViewTestCase): # Receive negative number post_data['line-1'] = -100 - + self.post(post_data, validate=False) # Receive 75 items diff --git a/InvenTree/order/tests.py b/InvenTree/order/tests.py index ed6a4ebb6a..1f35e54fb5 100644 --- a/InvenTree/order/tests.py +++ b/InvenTree/order/tests.py @@ -36,7 +36,7 @@ class OrderTest(TestCase): self.assertEqual(order.get_absolute_url(), '/order/purchase-order/1/') self.assertEqual(str(order), 'PO0001 - ACME') - + line = PurchaseOrderLineItem.objects.get(pk=1) self.assertEqual(str(line), "100 x ACME0001 from ACME (for PO0001 - ACME)") @@ -113,7 +113,7 @@ class OrderTest(TestCase): # Try to order a supplier part from the wrong supplier sku = SupplierPart.objects.get(SKU='ZERG-WIDGET') - + with self.assertRaises(django_exceptions.ValidationError): order.add_line_item(sku, 99) @@ -153,7 +153,7 @@ class OrderTest(TestCase): with self.assertRaises(django_exceptions.ValidationError): order.receive_line_item(line, loc, 'not a number', user=None) - + # Receive the rest of the items order.receive_line_item(line, loc, 50, user=None) diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index c62a3816d5..154b5ebd9c 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -152,7 +152,7 @@ class SalesOrderAttachmentCreate(AjaxCreateView): """ Save the user that uploaded the attachment """ - + attachment = form.save(commit=False) attachment.user = self.request.user attachment.save() @@ -330,7 +330,7 @@ class PurchaseOrderCreate(AjaxCreateView): order = form.save(commit=False) order.created_by = self.request.user - + return super().save(form) @@ -365,7 +365,7 @@ class SalesOrderCreate(AjaxCreateView): order = form.save(commit=False) order.created_by = self.request.user - + return super().save(form) @@ -414,7 +414,7 @@ class PurchaseOrderCancel(AjaxUpdateView): form_class = order_forms.CancelPurchaseOrderForm def validate(self, order, form, **kwargs): - + confirm = str2bool(form.cleaned_data.get('confirm', False)) if not confirm: @@ -536,11 +536,11 @@ class SalesOrderShip(AjaxUpdateView): order = self.get_object() self.object = order - + form = self.get_form() confirm = str2bool(request.POST.get('confirm', False)) - + valid = False if not confirm: @@ -823,7 +823,7 @@ class OrderParts(AjaxView): for supplier in self.suppliers: supplier.order_items = [] - + suppliers[supplier.name] = supplier for part in self.parts: @@ -844,9 +844,9 @@ class OrderParts(AjaxView): supplier.selected_purchase_order = orders.first().id else: supplier.selected_purchase_order = None - + suppliers[supplier.name] = supplier - + suppliers[supplier.name].order_items.append(part) self.suppliers = [suppliers[key] for key in suppliers.keys()] @@ -864,7 +864,7 @@ class OrderParts(AjaxView): if 'stock[]' in self.request.GET: stock_id_list = self.request.GET.getlist('stock[]') - + """ Get a list of all the parts associated with the stock items. - Base part must be purchaseable. - Return a set of corresponding Part IDs @@ -907,7 +907,7 @@ class OrderParts(AjaxView): parts = build.required_parts for part in parts: - + # If ordering from a Build page, ignore parts that we have enough of if part.quantity_to_order <= 0: continue @@ -963,19 +963,19 @@ class OrderParts(AjaxView): # Extract part information from the form for item in self.request.POST: - + if item.startswith('part-supplier-'): - + pk = item.replace('part-supplier-', '') - + # Check that the part actually exists try: part = Part.objects.get(id=pk) except (Part.DoesNotExist, ValueError): continue - + supplier_part_id = self.request.POST[item] - + quantity = self.request.POST.get('part-quantity-' + str(pk), 0) # Ensure a valid supplier has been passed @@ -1377,7 +1377,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin): self.form.fields['line'].widget = HiddenInput() else: self.form.add_error('line', _('Select line item')) - + if self.part: self.form.fields['part'].widget = HiddenInput() else: @@ -1412,7 +1412,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin): continue # Now we have a valid stock item - but can it be added to the sales order? - + # If not in stock, cannot be added to the order if not stock_item.in_stock: self.form.add_error( @@ -1480,7 +1480,7 @@ class SalesOrderAllocationCreate(AjaxCreateView): model = SalesOrderAllocation form_class = order_forms.CreateSalesOrderAllocationForm ajax_form_title = _('Allocate Stock to Order') - + def get_initial(self): initials = super().get_initial().copy() @@ -1495,10 +1495,10 @@ class SalesOrderAllocationCreate(AjaxCreateView): items = StockItem.objects.filter(part=line.part) quantity = line.quantity - line.allocated_quantity() - + if quantity < 0: quantity = 0 - + if items.count() == 1: item = items.first() initials['item'] = item @@ -1514,7 +1514,7 @@ class SalesOrderAllocationCreate(AjaxCreateView): return initials def get_form(self): - + form = super().get_form() line_id = form['line'].value() @@ -1542,10 +1542,10 @@ class SalesOrderAllocationCreate(AjaxCreateView): # Hide the 'line' field form.fields['line'].widget = HiddenInput() - + except (ValueError, SalesOrderLineItem.DoesNotExist): pass - + return form @@ -1554,7 +1554,7 @@ class SalesOrderAllocationEdit(AjaxUpdateView): model = SalesOrderAllocation form_class = order_forms.EditSalesOrderAllocationForm ajax_form_title = _('Edit Allocation Quantity') - + def get_form(self): form = super().get_form() diff --git a/InvenTree/part/admin.py b/InvenTree/part/admin.py index af2f615803..3945b56d7c 100644 --- a/InvenTree/part/admin.py +++ b/InvenTree/part/admin.py @@ -25,13 +25,13 @@ class PartResource(ModelResource): # ForeignKey fields category = Field(attribute='category', widget=widgets.ForeignKeyWidget(PartCategory)) - + default_location = Field(attribute='default_location', widget=widgets.ForeignKeyWidget(StockLocation)) default_supplier = Field(attribute='default_supplier', widget=widgets.ForeignKeyWidget(SupplierPart)) category_name = Field(attribute='category__name', readonly=True) - + variant_of = Field(attribute='variant_of', widget=widgets.ForeignKeyWidget(Part)) suppliers = Field(attribute='supplier_count', readonly=True) @@ -73,7 +73,7 @@ class PartResource(ModelResource): class PartAdmin(ImportExportModelAdmin): - + resource_class = PartResource list_display = ('full_name', 'description', 'total_stock', 'category') diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 6b26365b27..de6ac5f273 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -41,7 +41,7 @@ class PartCategoryTree(TreeSerializer): model = PartCategory queryset = PartCategory.objects.all() - + @property def root_url(self): return reverse('part-index') @@ -79,7 +79,7 @@ class CategoryList(generics.ListCreateAPIView): pass # Look for top-level categories elif isNull(cat_id): - + if not cascade: queryset = queryset.filter(parent=None) @@ -166,9 +166,9 @@ class CategoryParameters(generics.ListAPIView): parent_categories = category.get_ancestors() for parent in parent_categories: category_list.append(parent.pk) - + queryset = queryset.filter(category__in=category_list) - + return queryset @@ -264,7 +264,7 @@ class PartThumbs(generics.ListAPIView): # Get all Parts which have an associated image queryset = queryset.exclude(image='') - + return queryset def list(self, request, *args, **kwargs): @@ -301,7 +301,7 @@ class PartDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Part.objects.all() serializer_class = part_serializers.PartSerializer - + starred_parts = None def get_queryset(self, *args, **kwargs): @@ -482,7 +482,7 @@ class PartList(generics.ListCreateAPIView): def get_queryset(self, *args, **kwargs): queryset = super().get_queryset(*args, **kwargs) - + queryset = part_serializers.PartSerializer.prefetch_queryset(queryset) queryset = part_serializers.PartSerializer.annotate_queryset(queryset) @@ -576,7 +576,7 @@ class PartList(generics.ListCreateAPIView): if cat_id is None: # No category filtering if category is not specified pass - + else: # Category has been specified! if isNull(cat_id): @@ -780,10 +780,10 @@ class BomList(generics.ListCreateAPIView): kwargs['sub_part_detail'] = str2bool(self.request.GET.get('sub_part_detail', None)) except AttributeError: pass - + # Ensure the request context is passed through! kwargs['context'] = self.get_serializer_context() - + return self.serializer_class(*args, **kwargs) def get_queryset(self, *args, **kwargs): @@ -867,7 +867,7 @@ class BomList(generics.ListCreateAPIView): # Work out which lines have actually been validated pks = [] - + for bom_item in queryset.all(): if bom_item.is_line_valid: pks.append(bom_item.pk) @@ -915,7 +915,7 @@ class BomItemValidate(generics.UpdateAPIView): valid = request.data.get('valid', False) instance = self.get_object() - + serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) @@ -949,7 +949,7 @@ part_api_urls = [ url(r'^sale-price/', include([ url(r'^.*$', PartSalePriceList.as_view(), name='api-part-sale-price-list'), ])), - + # Base URL for PartParameter API endpoints url(r'^parameter/', include([ url(r'^template/$', PartParameterTemplateList.as_view(), name='api-part-param-template-list'), diff --git a/InvenTree/part/apps.py b/InvenTree/part/apps.py index 531b74442a..1b233bccac 100644 --- a/InvenTree/part/apps.py +++ b/InvenTree/part/apps.py @@ -43,7 +43,7 @@ class PartConfig(AppConfig): if part.image: url = part.image.thumbnail.name loc = os.path.join(settings.MEDIA_ROOT, url) - + if not os.path.exists(loc): logger.info("InvenTree: Generating thumbnail for Part '{p}'".format(p=part.name)) try: diff --git a/InvenTree/part/bom.py b/InvenTree/part/bom.py index b0f53c55eb..42f49f9dde 100644 --- a/InvenTree/part/bom.py +++ b/InvenTree/part/bom.py @@ -69,7 +69,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa for item in items: item.level = str(int(level)) - + # Avoid circular BOM references if item.pk in uids: continue @@ -79,7 +79,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa if item.sub_part.assembly: if max_levels is None or level < max_levels: add_items(item.sub_part.bom_items.all().order_by('id'), level + 1) - + if cascade: # Cascading (multi-level) BOM @@ -124,7 +124,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa parameter_cols[name].update({b_idx: value}) except KeyError: parameter_cols[name] = {b_idx: value} - + # Add parameter columns to dataset parameter_cols_ordered = OrderedDict(sorted(parameter_cols.items(), key=lambda x: x[0])) add_columns_to_dataset(parameter_cols_ordered, len(bom_items)) @@ -185,7 +185,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # Filter manufacturer parts manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk) manufacturer_parts = manufacturer_parts.prefetch_related('supplier_parts') - + # Process manufacturer part for manufacturer_idx, manufacturer_part in enumerate(manufacturer_parts): @@ -250,7 +250,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # Filter supplier parts manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk) - + for idx, manufacturer_part in enumerate(manufacturer_parts): if manufacturer_part: @@ -295,7 +295,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa # Filter supplier parts supplier_parts = SupplierPart.objects.filter(part__pk=b_part.pk) - + for idx, supplier_part in enumerate(supplier_parts): if supplier_part.supplier: @@ -326,7 +326,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa filename = '{n}_BOM.{fmt}'.format(n=part.full_name, fmt=fmt) return DownloadFile(data, filename) - + class BomUploadManager: """ Class for managing an uploaded BOM file """ @@ -342,7 +342,7 @@ class BomUploadManager: 'Part_IPN', 'Part_ID', ] - + # Fields which would be helpful but are not required OPTIONAL_HEADERS = [ 'Reference', @@ -360,7 +360,7 @@ class BomUploadManager: def __init__(self, bom_file): """ Initialize the BomUpload class with a user-uploaded file object """ - + self.process(bom_file) def process(self, bom_file): @@ -387,7 +387,7 @@ class BomUploadManager: def guess_header(self, header, threshold=80): """ Try to match a header (from the file) to a list of known headers - + Args: header - Header name to look for threshold - Match threshold for fuzzy search @@ -421,7 +421,7 @@ class BomUploadManager: return matches[0]['header'] return None - + def columns(self): """ Return a list of headers for the thingy """ headers = [] diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 131c6aeac7..8f6e3d8898 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -95,11 +95,11 @@ class BomExportForm(forms.Form): parameter_data = forms.BooleanField(label=_("Include Parameter Data"), required=False, initial=False, help_text=_("Include part parameters data in exported BOM")) stock_data = forms.BooleanField(label=_("Include Stock Data"), required=False, initial=False, help_text=_("Include part stock data in exported BOM")) - + manufacturer_data = forms.BooleanField(label=_("Include Manufacturer Data"), required=False, initial=True, help_text=_("Include part manufacturer data in exported BOM")) supplier_data = forms.BooleanField(label=_("Include Supplier Data"), required=False, initial=True, help_text=_("Include part supplier data in exported BOM")) - + def get_choices(self): """ BOM export format choices """ @@ -324,7 +324,7 @@ class EditCategoryParameterTemplateForm(HelperForm): add_to_all_categories = forms.BooleanField(required=False, initial=False, help_text=_('Add parameter template to all categories')) - + class Meta: model = PartCategoryParameterTemplate fields = [ diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 137781ba2b..b3955bed24 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -349,7 +349,7 @@ class Part(MPTTModel): context['available'] = self.available_stock context['on_order'] = self.on_order - + context['required'] = context['required_build_order_quantity'] + context['required_sales_order_quantity'] context['allocated'] = context['allocated_build_order_quantity'] + context['allocated_sales_order_quantity'] @@ -434,7 +434,7 @@ class Part(MPTTModel): a) The parent part is the same as this one b) The parent part is used in the BOM for *this* part c) The parent part is used in the BOM for any child parts under this one - + Failing this check raises a ValidationError! """ @@ -506,7 +506,7 @@ class Part(MPTTModel): parts = Part.objects.filter(tree_id=self.tree_id) stock = StockModels.StockItem.objects.filter(part__in=parts).exclude(serial=None) - + # There are no matchin StockItem objects (skip further tests) if not stock.exists(): return None @@ -578,7 +578,7 @@ class Part(MPTTModel): if self.IPN: elements.append(self.IPN) - + elements.append(self.name) if self.revision: @@ -663,7 +663,7 @@ class Part(MPTTModel): def clean(self): """ Perform cleaning operations for the Part model - + Update trackable status: If this part is trackable, and it is used in the BOM for a parent part which is *not* trackable, @@ -946,7 +946,7 @@ class Part(MPTTModel): quantity = 0 for build in builds: - + bom_item = None # List the bom lines required to make the build (including inherited ones!) @@ -958,7 +958,7 @@ class Part(MPTTModel): build_quantity = build.quantity * bom_item.quantity quantity += build_quantity - + return quantity def requiring_sales_orders(self): @@ -1008,7 +1008,7 @@ class Part(MPTTModel): def quantity_to_order(self): """ Return the quantity needing to be ordered for this part. - + Here, an "order" could be one of: - Build Order - Sales Order @@ -1019,7 +1019,7 @@ class Part(MPTTModel): Required for orders = self.required_order_quantity() Currently on order = self.on_order Currently building = self.quantity_being_built - + """ # Total requirement @@ -1114,7 +1114,7 @@ class Part(MPTTModel): if total is None: total = 0 - + return max(total, 0) @property @@ -1238,7 +1238,7 @@ class Part(MPTTModel): @property def total_stock(self): """ Return the total stock quantity for this part. - + - Part may be stored in multiple locations - If this part is a "template" (variants exist) then these are counted too """ @@ -1463,7 +1463,7 @@ class Part(MPTTModel): # Start with a list of all parts designated as 'sub components' parts = Part.objects.filter(component=True) - + # Exclude this part parts = parts.exclude(id=self.id) @@ -1496,7 +1496,7 @@ class Part(MPTTModel): def get_price_info(self, quantity=1, buy=True, bom=True): """ Return a simplified pricing string for this part - + Args: quantity: Number of units to calculate price for buy: Include supplier pricing (default = True) @@ -1519,7 +1519,7 @@ class Part(MPTTModel): return "{a} - {b}".format(a=min_price, b=max_price) def get_supplier_price_range(self, quantity=1): - + min_price = None max_price = None @@ -1586,7 +1586,7 @@ class Part(MPTTModel): return (min_price, max_price) def get_price_range(self, quantity=1, buy=True, bom=True): - + """ Return the price range for this part. This price can be either: - Supplier price (if purchased from suppliers) @@ -1645,7 +1645,7 @@ class Part(MPTTModel): @transaction.atomic def copy_parameters_from(self, other, **kwargs): - + clear = kwargs.get('clear', True) if clear: @@ -1692,7 +1692,7 @@ class Part(MPTTModel): # Copy the parameters data if kwargs.get('parameters', True): self.copy_parameters_from(other) - + # Copy the fields that aren't available in the duplicate form self.salable = other.salable self.assembly = other.assembly @@ -1722,7 +1722,7 @@ class Part(MPTTModel): tests = tests.filter(required=required) return tests - + def getRequiredTests(self): # Return the tests which are required by this part return self.getTestTemplates(required=True) @@ -1868,7 +1868,7 @@ class PartAttachment(InvenTreeAttachment): """ Model for storing file attachments against a Part object """ - + def getSubdir(self): return os.path.join("part_files", str(self.part.id)) @@ -2227,7 +2227,7 @@ class BomItem(models.Model): def validate_hash(self, valid=True): """ Mark this item as 'valid' (store the checksum hash). - + Args: valid: If true, validate the hash, otherwise invalidate it (default = True) """ @@ -2265,7 +2265,7 @@ class BomItem(models.Model): # Check for circular BOM references if self.sub_part: self.sub_part.checkAddToBOM(self.part) - + # If the sub_part is 'trackable' then the 'quantity' field must be an integer if self.sub_part.trackable: if not self.quantity == int(self.quantity): @@ -2301,7 +2301,7 @@ class BomItem(models.Model): """ query = self.sub_part.stock_items.all() - + query = query.prefetch_related([ 'sub_part__stock_items', ]) @@ -2358,7 +2358,7 @@ class BomItem(models.Model): def get_required_quantity(self, build_quantity): """ Calculate the required part quantity, based on the supplier build_quantity. Includes overage estimate in the returned value. - + Args: build_quantity: Number of parts to build diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 58df62283a..7ab385249c 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -134,7 +134,7 @@ class PartBriefSerializer(InvenTreeModelSerializer): """ Serializer for Part (brief detail) """ thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True) - + stock = serializers.FloatField(source='total_stock') class Meta: @@ -232,7 +232,7 @@ class PartSerializer(InvenTreeModelSerializer): output_field=models.DecimalField(), ) ) - + # Filter to limit orders to "open" order_filter = Q( order__status__in=PurchaseOrderStatus.OPEN @@ -259,7 +259,7 @@ class PartSerializer(InvenTreeModelSerializer): output_field=models.DecimalField(), ), ) - + return queryset def get_starred(self, part): @@ -358,7 +358,7 @@ class BomItemSerializer(InvenTreeModelSerializer): quantity = serializers.FloatField() part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True)) - + part_detail = PartBriefSerializer(source='part', many=False, read_only=True) sub_part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(component=True)) diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 536f25cb5b..cd2313e09c 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -47,7 +47,7 @@ def str2bool(x, *args, **kwargs): def inrange(n, *args, **kwargs): """ Return range(n) for iterating through a numeric quantity """ return range(n) - + @register.simple_tag() def multiply(x, y, *args, **kwargs): @@ -59,7 +59,7 @@ def multiply(x, y, *args, **kwargs): def add(x, y, *args, **kwargs): """ Add two numbers together """ return x + y - + @register.simple_tag() def part_allocation_count(build, part, *args, **kwargs): @@ -177,7 +177,7 @@ def authorized_owners(group): except TypeError: # group.get_users returns None pass - + return owners diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 4389003544..0f5f59d3a3 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -41,12 +41,12 @@ class PartAPITest(InvenTreeAPITestCase): Test that we can retrieve list of part categories, with various filtering options. """ - + url = reverse('api-part-category-list') - + # Request *all* part categories response = self.client.get(url, format='json') - + self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 8) @@ -95,7 +95,7 @@ class PartAPITest(InvenTreeAPITestCase): url = reverse('api-part-category-list') response = self.client.post(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) - + parent = response.data['pk'] # Add some sub-categories to the top-level 'Animals' category @@ -289,7 +289,7 @@ class PartAPITest(InvenTreeAPITestCase): self.assertIn('count', data) self.assertIn('results', data) - + self.assertEqual(len(data['results']), n) @@ -354,7 +354,7 @@ class PartAPIAggregationTest(InvenTreeAPITestCase): self.assertEqual(data['in_stock'], 600) self.assertEqual(data['stock_item_count'], 4) - + # Add some more stock items!! for i in range(100): StockItem.objects.create(part=self.part, quantity=5) @@ -463,7 +463,7 @@ class PartParameterTest(InvenTreeAPITestCase): response = self.client.patch(url, {'data': '15'}, format='json') self.assertEqual(response.status_code, 200) - + # Check that the data changed! response = self.client.get(url, format='json') diff --git a/InvenTree/part/test_bom_item.py b/InvenTree/part/test_bom_item.py index a518ca1ddc..7e553be73a 100644 --- a/InvenTree/part/test_bom_item.py +++ b/InvenTree/part/test_bom_item.py @@ -64,7 +64,7 @@ class BomItemTest(TestCase): """ Test that BOM line overages are calculated correctly """ item = BomItem.objects.get(part=100, sub_part=50) - + q = 300 item.quantity = q @@ -77,7 +77,7 @@ class BomItemTest(TestCase): item.overage = 'asf234?' n = item.get_overage_quantity(q) self.assertEqual(n, 0) - + # Test absolute overage item.overage = '3' n = item.get_overage_quantity(q) @@ -100,7 +100,7 @@ class BomItemTest(TestCase): """ Test BOM item hash encoding """ item = BomItem.objects.get(part=100, sub_part=50) - + h1 = item.get_item_hash() # Change data - the hash must change diff --git a/InvenTree/part/test_category.py b/InvenTree/part/test_category.py index b3aa7f1202..e616fc2054 100644 --- a/InvenTree/part/test_category.py +++ b/InvenTree/part/test_category.py @@ -59,7 +59,7 @@ class CategoryTest(TestCase): def test_unique_parents(self): """ Test the 'unique_parents' functionality """ - + parents = [item.pk for item in self.transceivers.getUniqueParents()] self.assertIn(self.electronics.id, parents) @@ -128,9 +128,9 @@ class CategoryTest(TestCase): with self.assertRaises(ValidationError) as err: cat.full_clean() cat.save() - + self.assertIn('Illegal character in name', str(err.exception.error_dict.get('name'))) - + cat.name = 'good name' cat.save() diff --git a/InvenTree/part/test_migrations.py b/InvenTree/part/test_migrations.py index 41fead4b30..9da287519e 100644 --- a/InvenTree/part/test_migrations.py +++ b/InvenTree/part/test_migrations.py @@ -34,7 +34,7 @@ class TestForwardMigrations(MigratorTestCase): # Initially some fields are not present with self.assertRaises(AttributeError): print(p.has_variants) - + with self.assertRaises(AttributeError): print(p.is_template) diff --git a/InvenTree/part/test_param.py b/InvenTree/part/test_param.py index 24eee44d89..4e6556e63d 100644 --- a/InvenTree/part/test_param.py +++ b/InvenTree/part/test_param.py @@ -32,7 +32,7 @@ class TestParams(TestCase): self.assertEqual(str(c1), 'Mechanical | Length | 2.8') def test_validate(self): - + n = PartParameterTemplate.objects.all().count() t1 = PartParameterTemplate(name='abcde', units='dd') diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 030d7faf4e..cd8726ccf4 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -91,7 +91,7 @@ class PartTest(TestCase): def test_rename_img(self): img = rename_part_image(self.r1, 'hello.png') self.assertEqual(img, os.path.join('part_images', 'hello.png')) - + def test_stock(self): # No stock of any resistors res = Part.objects.filter(description__contains='resistor') @@ -178,7 +178,7 @@ class PartSettingsTest(TestCase): Some fields for the Part model can have default values specified by the user. """ - + def setUp(self): # Create a user for auth user = get_user_model() @@ -251,7 +251,7 @@ class PartSettingsTest(TestCase): self.assertEqual(part.trackable, val) self.assertEqual(part.assembly, val) self.assertEqual(part.is_template, val) - + Part.objects.filter(pk=part.pk).delete() def test_duplicate_ipn(self): diff --git a/InvenTree/part/test_views.py b/InvenTree/part/test_views.py index 45fd39ceb0..c32753cbbb 100644 --- a/InvenTree/part/test_views.py +++ b/InvenTree/part/test_views.py @@ -9,7 +9,7 @@ from .models import Part, PartRelated class PartViewTestCase(TestCase): - + fixtures = [ 'category', 'part', @@ -24,7 +24,7 @@ class PartViewTestCase(TestCase): # Create a user user = get_user_model() - + self.user = user.objects.create_user( username='username', email='user@email.com', @@ -52,12 +52,12 @@ class PartListTest(PartViewTestCase): def test_part_index(self): response = self.client.get(reverse('part-index')) self.assertEqual(response.status_code, 200) - + keys = response.context.keys() self.assertIn('csrf_token', keys) self.assertIn('parts', keys) self.assertIn('user', keys) - + def test_export(self): """ Export part data to CSV """ @@ -153,7 +153,7 @@ class PartDetailTest(PartViewTestCase): response = self.client.get(reverse('bom-download', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) self.assertIn('streaming_content', dir(response)) - + class PartTests(PartViewTestCase): """ Tests for Part forms """ @@ -226,7 +226,7 @@ class PartRelatedTests(PartViewTestCase): response = self.client.post(reverse('part-related-create'), {'part_1': 1, 'part_2': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertContains(response, '"form_valid": false', status_code=200) - + # Check final count n = PartRelated.objects.all().count() self.assertEqual(n, 1) @@ -266,7 +266,7 @@ class PartQRTest(PartViewTestCase): def test_valid_part(self): response = self.client.get(reverse('part-qr', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + data = str(response.content) self.assertIn('Part QR Code', data) diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index b90b11b568..6579af019e 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -30,11 +30,11 @@ sale_price_break_urls = [ ] part_parameter_urls = [ - + url(r'^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'), url(r'^template/(?P\d+)/edit/', views.PartParameterTemplateEdit.as_view(), name='part-param-template-edit'), url(r'^template/(?P\d+)/delete/', views.PartParameterTemplateDelete.as_view(), name='part-param-template-edit'), - + url(r'^new/', views.PartParameterCreate.as_view(), name='part-param-create'), url(r'^(?P\d+)/edit/', views.PartParameterEdit.as_view(), name='part-param-edit'), url(r'^(?P\d+)/delete/', views.PartParameterDelete.as_view(), name='part-param-delete'), @@ -49,10 +49,10 @@ part_detail_urls = [ url(r'^duplicate/', views.PartDuplicate.as_view(), name='part-duplicate'), url(r'^make-variant/', views.MakePartVariant.as_view(), name='make-part-variant'), url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'), - + url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'), - + url(r'^params/', views.PartDetail.as_view(template_name='part/params.html'), name='part-params'), url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'), url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'), @@ -70,7 +70,7 @@ part_detail_urls = [ url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'), url(r'^attachments/?', views.PartDetail.as_view(template_name='part/attachments.html'), name='part-attachments'), url(r'^notes/?', views.PartNotes.as_view(), name='part-notes'), - + url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'), # Normal thumbnail with form @@ -104,7 +104,7 @@ category_urls = [ url(r'^subcategory/', views.CategoryDetail.as_view(template_name='part/subcategory.html'), name='category-subcategory'), url(r'^parametric/', views.CategoryParametric.as_view(), name='category-parametric'), - + # Anything else url(r'^.*$', views.CategoryDetail.as_view(), name='category-detail'), ])) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index d7c68dd6a3..001a258b0f 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -204,12 +204,12 @@ class PartAttachmentCreate(AjaxCreateView): class PartAttachmentEdit(AjaxUpdateView): """ View for editing a PartAttachment object """ - + model = PartAttachment form_class = part_forms.EditPartAttachmentForm ajax_template_name = 'modal_form.html' ajax_form_title = _('Edit attachment') - + def get_data(self): return { 'success': _('Part attachment updated') @@ -245,7 +245,7 @@ class PartTestTemplateCreate(AjaxCreateView): model = PartTestTemplate form_class = part_forms.EditPartTestTemplateForm ajax_form_title = _("Create Test Template") - + def get_initial(self): initials = super().get_initial() @@ -299,7 +299,7 @@ class PartSetCategory(AjaxUpdateView): category = None parts = [] - + def get(self, request, *args, **kwargs): """ Respond to a GET request to this view """ @@ -364,7 +364,7 @@ class PartSetCategory(AjaxUpdateView): ctx['category'] = self.category return ctx - + class MakePartVariant(AjaxCreateView): """ View for creating a new variant based on an existing template Part @@ -501,17 +501,17 @@ class PartDuplicate(AjaxCreateView): valid = form.is_valid() name = request.POST.get('name', None) - + if name: matches = match_part_names(name) if len(matches) > 0: # Display the first five closest matches context['matches'] = matches[:5] - + # Enforce display of the checkbox form.fields['confirm_creation'].widget = CheckboxInput() - + # Check if the user has checked the 'confirm_creation' input confirmed = str2bool(request.POST.get('confirm_creation', False)) @@ -565,7 +565,7 @@ class PartDuplicate(AjaxCreateView): initials = super(AjaxCreateView, self).get_initial() initials['bom_copy'] = str2bool(InvenTreeSetting.get_setting('PART_COPY_BOM', True)) - + initials['parameters_copy'] = str2bool(InvenTreeSetting.get_setting('PART_COPY_PARAMETERS', True)) return initials @@ -575,7 +575,7 @@ class PartCreate(AjaxCreateView): """ View for creating a new Part object. Options for providing initial conditions: - + - Provide a category object as initial data """ model = Part @@ -636,9 +636,9 @@ class PartCreate(AjaxCreateView): context = {} valid = form.is_valid() - + name = request.POST.get('name', None) - + if name: matches = match_part_names(name) @@ -646,17 +646,17 @@ class PartCreate(AjaxCreateView): # Limit to the top 5 matches (to prevent clutter) context['matches'] = matches[:5] - + # Enforce display of the checkbox form.fields['confirm_creation'].widget = CheckboxInput() - + # Check if the user has checked the 'confirm_creation' input confirmed = str2bool(request.POST.get('confirm_creation', False)) if not confirmed: msg = _('Possible matches exist - confirm creation of new part') form.add_error('confirm_creation', msg) - + form.pre_form_warning = msg valid = False @@ -705,7 +705,7 @@ class PartCreate(AjaxCreateView): initials['keywords'] = category.default_keywords except (PartCategory.DoesNotExist, ValueError): pass - + # Allow initial data to be passed through as arguments for label in ['name', 'IPN', 'description', 'revision', 'keywords']: if label in self.request.GET: @@ -734,7 +734,7 @@ class PartNotes(UpdateView): def get_success_url(self): """ Return the success URL for this form """ - + return reverse('part-notes', kwargs={'pk': self.get_object().id}) def get_context_data(self, **kwargs): @@ -767,7 +767,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView): - If '?editing=True', set 'editing_enabled' context variable """ context = super().get_context_data(**kwargs) - + part = self.get_object() if str2bool(self.request.GET.get('edit', '')): @@ -806,7 +806,7 @@ class PartDetailFromIPN(PartDetail): pass except queryset.model.DoesNotExist: pass - + return None def get(self, request, *args, **kwargs): @@ -1017,7 +1017,7 @@ class BomDuplicate(AjaxUpdateView): ajax_form_title = _('Duplicate BOM') ajax_template_name = 'part/bom_duplicate.html' form_class = part_forms.BomDuplicateForm - + def get_form(self): form = super().get_form() @@ -1218,7 +1218,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): def handleBomFileUpload(self): """ Process a BOM file upload form. - + This function validates that the uploaded file was valid, and contains tabulated data that can be extracted. If the file does not satisfy these requirements, @@ -1299,13 +1299,13 @@ class BomUpload(InvenTreeRoleMixin, FormView): - If using the Part_ID field, we can do an exact match against the PK field - If using the Part_IPN field, we can do an exact match against the IPN field - If using the Part_Name field, we can use fuzzy string matching to match "close" values - + We also extract other information from the row, for the other non-matched fields: - Quantity - Reference - Overage - Note - + """ # Initially use a quantity of zero @@ -1375,7 +1375,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): # Check if there is a column corresponding to "Note" field if n_idx >= 0: row['note'] = row['data'][n_idx] - + # Supply list of part options for each row, sorted by how closely they match the part name row['part_options'] = part_options @@ -1390,7 +1390,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): try: if row['part_ipn']: part_matches = [part for part in self.allowed_parts if part.IPN and row['part_ipn'].lower() == str(part.IPN.lower())] - + # Check for single match if len(part_matches) == 1: row['part_match'] = part_matches[0] @@ -1464,7 +1464,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): col_id = int(s[3]) except ValueError: continue - + if row_id not in self.row_data: self.row_data[row_id] = {} @@ -1530,7 +1530,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): if col in self.column_selections.values(): part_match_found = True break - + # If not, notify user if not part_match_found: for col in BomUploadManager.PART_MATCH_HEADERS: @@ -1546,7 +1546,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): self.getTableDataFromPost() valid = len(self.missing_columns) == 0 and not self.duplicates - + if valid: # Try to extract meaningful data self.preFillSelections() @@ -1557,7 +1557,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): return self.render_to_response(self.get_context_data(form=None)) def handlePartSelection(self): - + # Extract basic table data from POST request self.getTableDataFromPost() @@ -1595,7 +1595,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): row['errors']['quantity'] = _('Enter a valid quantity') row['quantity'] = q - + except ValueError: continue @@ -1648,7 +1648,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): if key.startswith(field + '_'): try: row_id = int(key.replace(field + '_', '')) - + row = self.getRowByIndex(row_id) if row: @@ -1714,7 +1714,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): return self.render_to_response(ctx) def getRowByIndex(self, idx): - + for row in self.bom_rows: if row['index'] == idx: return row @@ -1732,7 +1732,7 @@ class BomUpload(InvenTreeRoleMixin, FormView): self.form = self.get_form(self.get_form_class()) # Did the user POST a file named bom_file? - + form_step = request.POST.get('form_step', None) if form_step == 'select_file': @@ -1753,7 +1753,7 @@ class PartExport(AjaxView): def get_parts(self, request): """ Extract part list from the POST parameters. Parts can be supplied as: - + - Part category - List of part PK values """ @@ -1956,10 +1956,10 @@ class PartPricing(AjaxView): form_class = part_forms.PartPriceForm role_required = ['sales_order.view', 'part.view'] - + def get_quantity(self): """ Return set quantity in decimal format """ - + return Decimal(self.request.POST.get('quantity', 1)) def get_part(self): @@ -1985,7 +1985,7 @@ class PartPricing(AjaxView): scaler = Decimal(1.0) part = self.get_part() - + ctx = { 'part': part, 'quantity': quantity, @@ -2039,7 +2039,7 @@ class PartPricing(AjaxView): if min_bom_price: ctx['min_total_bom_price'] = min_bom_price ctx['min_unit_bom_price'] = min_unit_bom_price - + if max_bom_price: ctx['max_total_bom_price'] = max_bom_price ctx['max_unit_bom_price'] = max_unit_bom_price @@ -2168,7 +2168,7 @@ class PartParameterDelete(AjaxDeleteView): model = PartParameter ajax_template_name = 'part/param_delete.html' ajax_form_title = _('Delete Part Parameter') - + class CategoryDetail(InvenTreeRoleMixin, DetailView): """ Detail view for PartCategory """ @@ -2223,7 +2223,7 @@ class CategoryEdit(AjaxUpdateView): """ Update view to edit a PartCategory """ - + model = PartCategory form_class = part_forms.EditCategoryForm ajax_template_name = 'modal_form.html' @@ -2244,9 +2244,9 @@ class CategoryEdit(AjaxUpdateView): Limit the choices for 'parent' field to those which make sense """ - + form = super(AjaxUpdateView, self).get_form() - + category = self.get_object() # Remove any invalid choices for the parent category part @@ -2262,7 +2262,7 @@ class CategoryDelete(AjaxDeleteView): """ Delete view to delete a PartCategory """ - + model = PartCategory ajax_template_name = 'part/category_delete.html' ajax_form_title = _('Delete Part Category') @@ -2346,7 +2346,7 @@ class CategoryParameterTemplateCreate(AjaxCreateView): """ form = super(AjaxCreateView, self).get_form() - + form.fields['category'].widget = HiddenInput() if form.is_valid(): @@ -2441,7 +2441,7 @@ class CategoryParameterTemplateEdit(AjaxUpdateView): """ form = super(AjaxUpdateView, self).get_form() - + form.fields['category'].widget = HiddenInput() form.fields['add_to_all_categories'].widget = HiddenInput() form.fields['add_to_same_level_categories'].widget = HiddenInput() @@ -2495,7 +2495,7 @@ class BomItemCreate(AjaxCreateView): """ Create view for making a new BomItem object """ - + model = BomItem form_class = part_forms.EditBomItemForm ajax_template_name = 'modal_form.html' @@ -2523,13 +2523,13 @@ class BomItemCreate(AjaxCreateView): try: part = Part.objects.get(id=part_id) - + # Hide the 'part' field form.fields['part'].widget = HiddenInput() # Exclude the part from its own BOM sub_part_query = sub_part_query.exclude(id=part.id) - + # Eliminate any options that are already in the BOM! sub_part_query = sub_part_query.exclude(id__in=[item.id for item in part.getRequiredParts()]) @@ -2634,7 +2634,7 @@ class PartSalePriceBreakCreate(AjaxCreateView): model = PartSellPriceBreak form_class = part_forms.EditPartSalePriceBreakForm ajax_form_title = _('Add Price Break') - + def get_data(self): return { 'success': _('Added new price break') @@ -2645,7 +2645,7 @@ class PartSalePriceBreakCreate(AjaxCreateView): part = Part.objects.get(id=self.request.GET.get('part')) except (ValueError, Part.DoesNotExist): part = None - + if part is None: try: part = Part.objects.get(id=self.request.POST.get('part')) @@ -2690,7 +2690,7 @@ class PartSalePriceBreakEdit(AjaxUpdateView): return form - + class PartSalePriceBreakDelete(AjaxDeleteView): """ View for deleting a sale price break """ diff --git a/InvenTree/plugins/action/action.py b/InvenTree/plugins/action/action.py index d61838f49b..8b9ed6aec9 100644 --- a/InvenTree/plugins/action/action.py +++ b/InvenTree/plugins/action/action.py @@ -23,10 +23,10 @@ class ActionPlugin(plugin.InvenTreePlugin): look at the PLUGIN_NAME instead. """ action = cls.ACTION_NAME - + if not action: action = cls.PLUGIN_NAME - + return action def __init__(self, user, data=None): diff --git a/InvenTree/report/api.py b/InvenTree/report/api.py index 0925cc5249..351a988601 100644 --- a/InvenTree/report/api.py +++ b/InvenTree/report/api.py @@ -62,7 +62,7 @@ class StockItemReportMixin: """ Return a list of requested stock items """ - + items = [] params = self.request.query_params @@ -101,7 +101,7 @@ class BuildReportMixin: params = self.request.query_params for key in ['build', 'build[]', 'builds', 'builds[]']: - + if key in params: builds = params.getlist(key, []) @@ -268,7 +268,7 @@ class StockItemTestReportList(ReportListView, StockItemReportMixin): serializer_class = TestReportSerializer def filter_queryset(self, queryset): - + queryset = super().filter_queryset(queryset) # List of StockItem objects to match against @@ -342,7 +342,7 @@ class StockItemTestReportPrint(generics.RetrieveAPIView, StockItemReportMixin, R items = self.get_items() return self.print(request, items) - + class BOMReportList(ReportListView, PartReportMixin): """ @@ -459,7 +459,7 @@ class BuildReportList(ReportListView, BuildReportMixin): We need to compare the 'filters' string of each report, and see if it matches against each of the specified parts - + # TODO: This code needs some refactoring! """ @@ -546,7 +546,7 @@ class POReportList(ReportListView, OrderReportMixin): valid_report_ids = set() for report in queryset.all(): - + matches = True # Filter string defined for the report object @@ -565,7 +565,7 @@ class POReportList(ReportListView, OrderReportMixin): except FieldError: matches = False break - + if matches: valid_report_ids.add(report.pk) else: @@ -629,7 +629,7 @@ class SOReportList(ReportListView, OrderReportMixin): valid_report_ids = set() for report in queryset.all(): - + matches = True # Filter string defined for the report object @@ -648,7 +648,7 @@ class SOReportList(ReportListView, OrderReportMixin): except FieldError: matches = False break - + if matches: valid_report_ids.add(report.pk) else: diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index 4e218a2c50..fa7ae2b271 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -52,7 +52,7 @@ class ReportFileUpload(FileSystemStorage): For example, a snippet or asset file is referenced in a template by filename, and we do not want that filename to change when we upload a new *version* of the snippet or asset file. - + This uploader class performs the following pseudo-code function: - If the model is *new*, proceed as normal @@ -408,7 +408,7 @@ class PurchaseOrderReport(ReportTemplateBase): @classmethod def getSubdir(cls): return 'purchaseorder' - + filters = models.CharField( blank=True, max_length=250, @@ -479,7 +479,7 @@ def rename_snippet(instance, filename): if str(filename) == str(instance.snippet): fullpath = os.path.join(settings.MEDIA_ROOT, path) fullpath = os.path.abspath(fullpath) - + if os.path.exists(fullpath): logger.info(f"Deleting existing snippet file: '{filename}'") os.remove(fullpath) diff --git a/InvenTree/report/templatetags/barcode.py b/InvenTree/report/templatetags/barcode.py index e38fab1f06..a47d45fdf0 100644 --- a/InvenTree/report/templatetags/barcode.py +++ b/InvenTree/report/templatetags/barcode.py @@ -22,7 +22,7 @@ def image_data(img, fmt='PNG'): buffered = BytesIO() img.save(buffered, format=fmt) - + img_str = base64.b64encode(buffered.getvalue()) return f"data:image/{fmt.lower()};charset=utf-8;base64," + img_str.decode() diff --git a/InvenTree/report/templatetags/report.py b/InvenTree/report/templatetags/report.py index 8ff15ccdee..45d11c1d2d 100644 --- a/InvenTree/report/templatetags/report.py +++ b/InvenTree/report/templatetags/report.py @@ -104,7 +104,7 @@ def company_image(company): path = os.path.abspath(path) return f"file://{path}" - + @register.simple_tag() def internal_link(link, text): diff --git a/InvenTree/script/translate.py b/InvenTree/script/translate.py index 3a08c0b410..b41bb96788 100644 --- a/InvenTree/script/translate.py +++ b/InvenTree/script/translate.py @@ -29,7 +29,7 @@ def manually_translate_file(filename, save=False): print("a) Directly enter a new tranlation in the target language") print("b) Leave empty to skip") print("c) Press Ctrl+C to exit") - + print("-------------------------") input("Press to start") print("") diff --git a/InvenTree/script/translation_stats.py b/InvenTree/script/translation_stats.py index 0ba969479b..f47a21f168 100644 --- a/InvenTree/script/translation_stats.py +++ b/InvenTree/script/translation_stats.py @@ -64,5 +64,5 @@ if __name__ == '__main__': percentage = 0 print(f"| {locale.ljust(4, ' ')} : {str(percentage).rjust(4, ' ')}% |") - + print("-" * 16) diff --git a/InvenTree/stock/admin.py b/InvenTree/stock/admin.py index 5f3c08839d..f59c44467e 100644 --- a/InvenTree/stock/admin.py +++ b/InvenTree/stock/admin.py @@ -87,7 +87,7 @@ class StockItemResource(ModelResource): # Date management updated = Field(attribute='updated', widget=widgets.DateWidget()) - + stocktake_date = Field(attribute='stocktake_date', widget=widgets.DateWidget()) def after_import(self, dataset, result, using_transactions, dry_run, **kwargs): @@ -127,7 +127,7 @@ class StockItemAdmin(ImportExportModelAdmin): class StockAttachmentAdmin(admin.ModelAdmin): list_display = ('stock_item', 'attachment', 'comment') - + class StockTrackingAdmin(ImportExportModelAdmin): list_display = ('item', 'date', 'title') diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 0e64cecdbd..b70b379e69 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -117,7 +117,7 @@ class StockAdjust(APIView): A generic class for handling stocktake actions. Subclasses exist for: - + - StockCount: count stock items - StockAdd: add stock items - StockRemove: remove stock items @@ -184,7 +184,7 @@ class StockCount(StockAdjust): """ Endpoint for counting stock (performing a stocktake). """ - + def post(self, request, *args, **kwargs): self.get_items(request) @@ -225,7 +225,7 @@ class StockRemove(StockAdjust): def post(self, request, *args, **kwargs): self.get_items(request) - + n = 0 for item in self.items: @@ -292,7 +292,7 @@ class StockLocationList(generics.ListCreateAPIView): params = self.request.query_params loc_id = params.get('parent', None) - + cascade = str2bool(params.get('cascade', False)) # Do not filter by location @@ -304,7 +304,7 @@ class StockLocationList(generics.ListCreateAPIView): # If we allow "cascade" at the top-level, this essentially means *all* locations if not cascade: queryset = queryset.filter(parent=None) - + else: try: @@ -321,7 +321,7 @@ class StockLocationList(generics.ListCreateAPIView): except (ValueError, StockLocation.DoesNotExist): pass - + return queryset filter_backends = [ @@ -379,14 +379,14 @@ class StockList(generics.ListCreateAPIView): # A location was *not* specified - try to infer it if 'location' not in request.data: location = item.part.get_default_location() - + if location is not None: item.location = location item.save() # An expiry date was *not* specified - try to infer it! if 'expiry_date' not in request.data: - + if item.part.default_expiry > 0: item.expiry_date = datetime.now().date() + timedelta(days=item.part.default_expiry) item.save() @@ -399,7 +399,7 @@ class StockList(generics.ListCreateAPIView): """ Override the 'list' method, as the StockLocation objects are very expensive to serialize. - + So, we fetch and serialize the required StockLocation objects only as required. """ @@ -601,7 +601,7 @@ class StockList(generics.ListCreateAPIView): if stale_days > 0: stale_date = datetime.now().date() + timedelta(days=stale_days) - + stale_filter = StockItem.IN_STOCK_FILTER & ~Q(expiry_date=None) & Q(expiry_date__lt=stale_date) if stale: @@ -652,7 +652,7 @@ class StockList(generics.ListCreateAPIView): if serial_number_gte is not None: queryset = queryset.filter(serial__gte=serial_number_gte) - + if serial_number_lte is not None: queryset = queryset.filter(serial__lte=serial_number_lte) @@ -681,7 +681,7 @@ class StockList(generics.ListCreateAPIView): else: # Filter StockItem without build allocations or sales order allocations queryset = queryset.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True)) - + # Do we wish to filter by "active parts" active = params.get('active', None) @@ -766,7 +766,7 @@ class StockList(generics.ListCreateAPIView): queryset = queryset.filter(location__in=location.getUniqueChildren()) else: queryset = queryset.filter(location=loc_id) - + except (ValueError, StockLocation.DoesNotExist): pass @@ -994,14 +994,14 @@ class StockTrackingList(generics.ListCreateAPIView): def create(self, request, *args, **kwargs): """ Create a new StockItemTracking object - + Here we override the default 'create' implementation, to save the user information associated with the request object. """ serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - + # Record the user who created this Part object item = serializer.save() item.user = request.user diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py index c784b08a69..3fb72ebe1e 100644 --- a/InvenTree/stock/forms.py +++ b/InvenTree/stock/forms.py @@ -118,7 +118,7 @@ class CreateStockItemForm(HelperForm): serial_numbers = forms.CharField(label=_('Serial Numbers'), required=False, help_text=_('Enter unique serial numbers (or leave blank)')) def __init__(self, *args, **kwargs): - + self.field_prefix = { 'serial_numbers': 'fa-hashtag', 'link': 'fa-link', @@ -147,17 +147,17 @@ class CreateStockItemForm(HelperForm): # Custom clean to prevent complex StockItem.clean() logic from running (yet) def full_clean(self): self._errors = ErrorDict() - + if not self.is_bound: # Stop further processing. return - + self.cleaned_data = {} # If the form is permitted to be empty, and none of the form data has # changed from the initial data, short circuit any validation. if self.empty_permitted and not self.has_changed(): return - + # Don't run _post_clean() as this will run StockItem.clean() self._clean_fields() self._clean_form() @@ -167,9 +167,9 @@ class SerializeStockForm(HelperForm): """ Form for serializing a StockItem. """ destination = TreeNodeChoiceField(queryset=StockLocation.objects.all(), label=_('Destination'), required=True, help_text=_('Destination for serialized stock (by default, will remain in current location)')) - + serial_numbers = forms.CharField(label=_('Serial numbers'), required=True, help_text=_('Unique serial numbers (must match quantity)')) - + note = forms.CharField(label=_('Notes'), required=False, help_text=_('Add transaction note (optional)')) quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5, label=_('Quantity')) @@ -240,7 +240,7 @@ class TestReportFormatForm(HelperForm): super().__init__(*args, **kwargs) self.fields['template'].choices = self.get_template_choices() - + def get_template_choices(self): """ Generate a list of of TestReport options for the StockItem @@ -337,7 +337,7 @@ class InstallStockForm(HelperForm): raise ValidationError({'quantity_to_install': _('Must not exceed available quantity')}) return data - + class UninstallStockForm(forms.ModelForm): """ @@ -373,11 +373,11 @@ class AdjustStockForm(forms.ModelForm): """ destination = TreeNodeChoiceField(queryset=StockLocation.objects.all(), label=_('Destination'), required=True, help_text=_('Destination stock location')) - + note = forms.CharField(label=_('Notes'), required=True, help_text=_('Add note (required)')) - + # transaction = forms.BooleanField(required=False, initial=False, label='Create Transaction', help_text='Create a stock transaction for these parts') - + confirm = forms.BooleanField(required=False, initial=False, label=_('Confirm stock adjustment'), help_text=_('Confirm movement of stock items')) set_loc = forms.BooleanField(required=False, initial=False, label=_('Set Default Location'), help_text=_('Set the destination as the default location for selected parts')) @@ -396,7 +396,7 @@ class AdjustStockForm(forms.ModelForm): class EditStockItemForm(HelperForm): """ Form for editing a StockItem object. Note that not all fields can be edited here (even if they can be specified during creation. - + location - Must be updated in a 'move' transaction quantity - Must be updated in a 'stocktake' transaction part - Cannot be edited after creation diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 7d9520a544..125a534f08 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -131,7 +131,7 @@ def before_delete_stock_location(sender, instance, using, **kwargs): class StockItem(MPTTModel): """ A StockItem object represents a quantity of physical instances of a part. - + Attributes: parent: Link to another StockItem from which this StockItem was created uid: Field containing a unique-id which is mapped to a third-party identifier (e.g. a barcode) @@ -191,7 +191,7 @@ class StockItem(MPTTModel): add_note = False user = kwargs.pop('user', None) - + add_note = add_note and kwargs.pop('note', True) super(StockItem, self).save(*args, **kwargs) @@ -226,7 +226,7 @@ class StockItem(MPTTModel): """ super(StockItem, self).validate_unique(exclude) - + # If the serial number is set, make sure it is not a duplicate if self.serial is not None: # Query to look for duplicate serial numbers @@ -421,7 +421,7 @@ class StockItem(MPTTModel): max_length=100, blank=True, null=True, help_text=_('Serial number for this item') ) - + link = InvenTreeURLField( verbose_name=_('External Link'), max_length=125, blank=True, @@ -727,7 +727,7 @@ class StockItem(MPTTModel): items = StockItem.objects.filter(belongs_to=self) for item in items: - + # Prevent duplication or recursion if item == self or item in installed: continue @@ -906,7 +906,7 @@ class StockItem(MPTTModel): Brief automated note detailing a movement or quantity change. """ - + track = StockItemTracking.objects.create( item=self, title=title, @@ -970,7 +970,7 @@ class StockItem(MPTTModel): # Create a new stock item for each unique serial number for serial in serials: - + # Create a copy of this StockItem new_item = StockItem.objects.get(pk=self.pk) new_item.quantity = 1 @@ -1001,7 +1001,7 @@ class StockItem(MPTTModel): """ Copy stock history from another StockItem """ for item in other.tracking_info.all(): - + item.item = self item.pk = None item.save() @@ -1151,7 +1151,7 @@ class StockItem(MPTTModel): @transaction.atomic def updateQuantity(self, quantity): """ Update stock quantity for this item. - + If the quantity has reached zero, this StockItem will be deleted. Returns: @@ -1174,7 +1174,7 @@ class StockItem(MPTTModel): self.quantity = quantity if quantity == 0 and self.delete_on_deplete and self.can_delete(): - + # TODO - Do not actually "delete" stock at this point - instead give it a "DELETED" flag self.delete() return False @@ -1584,7 +1584,7 @@ class StockItemTestResult(models.Model): with automated testing setups. Multiple results can be recorded against any given test, allowing tests to be run many times. - + Attributes: stock_item: Link to StockItem test: Test name (simple string matching) @@ -1613,7 +1613,7 @@ class StockItemTestResult(models.Model): for template in templates: if key == template.key: - + if template.requires_value: if not self.value: raise ValidationError({ diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 5b00c1dd17..4991a44e6f 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -140,7 +140,7 @@ class StockItemSerializer(InvenTreeModelSerializer): return queryset status_text = serializers.CharField(source='get_status_display', read_only=True) - + supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True) part_detail = PartBriefSerializer(source='part', many=False, read_only=True) @@ -150,7 +150,7 @@ class StockItemSerializer(InvenTreeModelSerializer): tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False) quantity = serializers.FloatField() - + allocated = serializers.FloatField(source='allocation_count', required=False) expired = serializers.BooleanField(required=False, read_only=True) diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index ae0d6fd862..e1fb616335 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -38,7 +38,7 @@ class StockAPITestCase(InvenTreeAPITestCase): ] def setUp(self): - + super().setUp() @@ -105,7 +105,7 @@ class StockItemListTest(StockAPITestCase): """ response = self.get_stock(part=25) - + self.assertEqual(len(response), 8) response = self.get_stock(part=10004) @@ -339,7 +339,7 @@ class StockItemTest(StockAPITestCase): ) self.assertContains(response, 'This field is required', status_code=status.HTTP_400_BAD_REQUEST) - + # POST with an invalid part reference response = self.client.post( @@ -384,10 +384,10 @@ class StockItemTest(StockAPITestCase): - Otherwise, check if the referenced part has a default_expiry defined - If so, use that! - Otherwise, no expiry - + Notes: - Part <25> has a default_expiry of 10 days - + """ # First test - create a new StockItem without an expiry date @@ -460,7 +460,7 @@ class StocktakeTest(StockAPITestCase): data['items'] = [{ 'pk': 10 }] - + response = self.post(url, data) self.assertContains(response, 'must contain a valid pk', status_code=status.HTTP_400_BAD_REQUEST) @@ -478,12 +478,12 @@ class StocktakeTest(StockAPITestCase): response = self.post(url, data) self.assertContains(response, 'must contain a valid quantity', status_code=status.HTTP_400_BAD_REQUEST) - + data['items'] = [{ 'pk': 1234, 'quantity': "-1.234" }] - + response = self.post(url, data) self.assertContains(response, 'must not be less than zero', status_code=status.HTTP_400_BAD_REQUEST) diff --git a/InvenTree/stock/test_views.py b/InvenTree/stock/test_views.py index 261598ae22..c565532739 100644 --- a/InvenTree/stock/test_views.py +++ b/InvenTree/stock/test_views.py @@ -29,7 +29,7 @@ class StockViewTestCase(TestCase): # Create a user user = get_user_model() - + self.user = user.objects.create_user( username='username', email='user@email.com', @@ -91,7 +91,7 @@ class StockLocationTest(StockViewTestCase): # Create with an invalid parent response = self.client.get(reverse('stock-location-create'), {'location': 999}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) - + class StockItemTest(StockViewTestCase): """" Tests for StockItem views """ @@ -211,7 +211,7 @@ class StockItemTest(StockViewTestCase): 'serial_numbers': 'dd-23-adf', 'destination': 'blorg' } - + # POST response = self.client.post(url, data_valid, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, 200) @@ -247,7 +247,7 @@ class StockOwnershipTest(StockViewTestCase): # Create a new user user = get_user_model() - + self.new_user = user.objects.create_user( username='john', email='john@email.com', @@ -314,7 +314,7 @@ class StockOwnershipTest(StockViewTestCase): response = self.client.post(reverse('stock-location-edit', args=(test_location_id,)), {'name': 'Office', 'owner': new_user_group_owner.pk}, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - + # Make sure the location's owner is unchanged location = StockLocation.objects.get(pk=test_location_id) self.assertEqual(location.owner, user_group_owner) @@ -366,7 +366,7 @@ class StockOwnershipTest(StockViewTestCase): response = self.client.post(reverse('stock-location-create'), new_location, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertContains(response, '"form_valid": true', status_code=200) - + # Retrieve created location location_created = StockLocation.objects.get(name=new_location['name']) diff --git a/InvenTree/stock/tests.py b/InvenTree/stock/tests.py index f3ca949bbf..08fa727547 100644 --- a/InvenTree/stock/tests.py +++ b/InvenTree/stock/tests.py @@ -144,7 +144,7 @@ class StockTest(TestCase): self.drawer3.save() self.assertNotEqual(self.drawer3.parent, self.office) - + self.assertEqual(self.drawer3.pathstring, 'Home/Drawer_3') def test_children(self): @@ -486,7 +486,7 @@ class VariantTest(StockTest): # Attempt to create the same serial number but for a variant (should fail!) item.pk = None item.part = Part.objects.get(pk=10004) - + with self.assertRaises(ValidationError): item.save() @@ -542,7 +542,7 @@ class TestResultTest(StockTest): test='sew cushion', result=True ) - + # Still should be failing at this point, # as the most recent "apply paint" test was False self.assertFalse(item.passedAllRequiredTests()) diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index 24e609fa4f..fe5472003f 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -14,7 +14,7 @@ location_urls = [ url(r'^edit/?', views.StockLocationEdit.as_view(), name='stock-location-edit'), url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'), url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'), - + url(r'sublocation/', views.StockLocationDetail.as_view(template_name='stock/sublocation.html'), name='stock-location-sublocation'), # Anything else diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 72395a54d0..0984405055 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -121,7 +121,7 @@ class StockLocationEdit(AjaxUpdateView): context_object_name = 'location' ajax_template_name = 'modal_form.html' ajax_form_title = _('Edit Stock Location') - + def get_form(self): """ Customize form data for StockLocation editing. @@ -182,7 +182,7 @@ class StockLocationEdit(AjaxUpdateView): """ self.object = form.save() - + # Is ownership control enabled? stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL') @@ -267,7 +267,7 @@ class StockItemAttachmentCreate(AjaxCreateView): def save(self, form, **kwargs): """ Record the user that uploaded the attachment """ - + attachment = form.save(commit=False) attachment.user = self.request.user attachment.save() @@ -297,7 +297,7 @@ class StockItemAttachmentCreate(AjaxCreateView): form = super().get_form() form.fields['stock_item'].widget = HiddenInput() - + return form @@ -309,7 +309,7 @@ class StockItemAttachmentEdit(AjaxUpdateView): model = StockItemAttachment form_class = StockForms.EditStockItemAttachmentForm ajax_form_title = _("Edit Stock Item Attachment") - + def get_form(self): form = super().get_form() @@ -327,7 +327,7 @@ class StockItemAttachmentDelete(AjaxDeleteView): ajax_form_title = _("Delete Stock Item Attachment") ajax_template_name = "attachment_delete.html" context_object_name = "attachment" - + def get_data(self): return { 'danger': _("Deleted attachment"), @@ -376,7 +376,7 @@ class StockItemReturnToStock(AjaxUpdateView): ajax_form_title = _("Return to Stock") context_object_name = "item" form_class = StockForms.ReturnStockItemForm - + def validate(self, item, form, **kwargs): location = form.cleaned_data.get('location', None) @@ -405,7 +405,7 @@ class StockItemDeleteTestData(AjaxUpdateView): model = StockItem form_class = ConfirmForm ajax_form_title = _("Delete All Test Data") - + role_required = ['stock.change', 'stock.delete'] def get_form(self): @@ -417,7 +417,7 @@ class StockItemDeleteTestData(AjaxUpdateView): stock_item = StockItem.objects.get(pk=self.kwargs['pk']) form = self.get_form() - + confirm = str2bool(request.POST.get('confirm', False)) if confirm is not True: @@ -488,7 +488,7 @@ class StockItemTestResultEdit(AjaxUpdateView): form = super().get_form() form.fields['stock_item'].widget = HiddenInput() - + return form @@ -545,11 +545,11 @@ class StockExport(AjaxView): def get(self, request, *args, **kwargs): export_format = request.GET.get('format', 'csv').lower() - + # Check if a particular location was specified loc_id = request.GET.get('location', None) location = None - + if loc_id: try: location = StockLocation.objects.get(pk=loc_id) @@ -646,9 +646,9 @@ class StockItemInstall(AjaxUpdateView): In contrast to the StockItemUninstall view, only a single stock item can be installed at once. - + The "part" to be installed must be provided in the GET query parameters. - + """ model = StockItem @@ -664,7 +664,7 @@ class StockItemInstall(AjaxUpdateView): Requirements: - Items must be in stock - + Filters: - Items can be filtered by Part reference """ @@ -702,7 +702,7 @@ class StockItemInstall(AjaxUpdateView): if self.part: initials['part'] = self.part - + return initials def get_form(self): @@ -875,13 +875,13 @@ class StockItemUninstall(AjaxView, FormMixin): class StockAdjust(AjaxView, FormMixin): """ View for enacting simple stock adjustments: - + - Take items from stock - Add items to stock - Count items - Move stock - Delete stock items - + """ ajax_template_name = 'stock/stock_adjust.html' @@ -942,7 +942,7 @@ class StockAdjust(AjaxView, FormMixin): for item in self.request.POST: if item.startswith('stock-id-'): - + pk = item.replace('stock-id-', '') q = self.request.POST[item] @@ -1022,9 +1022,9 @@ class StockAdjust(AjaxView, FormMixin): form = self.get_form() valid = form.is_valid() - + for item in self.stock_items: - + try: item.new_quantity = Decimal(item.new_quantity) except ValueError: @@ -1067,7 +1067,7 @@ class StockAdjust(AjaxView, FormMixin): # Was the entire stock taken? item = self.stock_items[0] - + if item.quantity == 0: # Instruct the form to redirect data['url'] = reverse('stock-index') @@ -1107,7 +1107,7 @@ class StockAdjust(AjaxView, FormMixin): return _('No action performed') def do_add(self): - + count = 0 note = self.request.POST['note'] @@ -1137,12 +1137,12 @@ class StockAdjust(AjaxView, FormMixin): return _('Removed stock from {n} items').format(n=count) def do_count(self): - + count = 0 note = self.request.POST['note'] for item in self.stock_items: - + item.stocktake(item.new_quantity, self.request.user, notes=note) count += 1 @@ -1165,7 +1165,7 @@ class StockAdjust(AjaxView, FormMixin): if set_loc: item.part.default_location = destination item.part.save() - + # Do not move to the same location (unless the quantity is different) if destination == item.location and item.new_quantity == item.quantity: continue @@ -1188,7 +1188,7 @@ class StockAdjust(AjaxView, FormMixin): if count == 0: return _('No items were moved') - + else: return _('Moved {n} items to {dest}').format( n=count, @@ -1201,7 +1201,7 @@ class StockAdjust(AjaxView, FormMixin): # note = self.request.POST['note'] for item in self.stock_items: - + # TODO - In the future, StockItems should not be 'deleted' # TODO - Instead, they should be marked as "inactive" @@ -1475,7 +1475,7 @@ class StockItemSerialize(AjaxUpdateView): return initials def get(self, request, *args, **kwargs): - + return super().get(request, *args, **kwargs) def post(self, request, *args, **kwargs): @@ -1503,13 +1503,13 @@ class StockItemSerialize(AjaxUpdateView): form.add_error('serial_numbers', e.messages) valid = False numbers = [] - + if valid: try: item.serializeStock(quantity, numbers, user, notes=notes, location=destination) except ValidationError as e: messages = e.message_dict - + for k in messages.keys(): if k in ['quantity', 'destination', 'serial_numbers']: form.add_error(k, messages[k]) @@ -1595,7 +1595,7 @@ class StockItemCreate(AjaxCreateView): if not part.purchaseable: form.fields.pop('purchase_price') - + # Hide the 'part' field (as a valid part is selected) # form.fields['part'].widget = HiddenInput() @@ -1658,7 +1658,7 @@ class StockItemCreate(AjaxCreateView): if type(location_owner.owner) is Group: user_as_owner = Owner.get_owner(self.request.user) queryset = location_owner.get_related_owners() - + if user_as_owner in queryset: form.fields['owner'].initial = user_as_owner @@ -1668,7 +1668,7 @@ class StockItemCreate(AjaxCreateView): # If location's owner is a user: automatically set owner field and disable it form.fields['owner'].disabled = True form.fields['owner'].initial = location_owner - + return form def get_initial(self): @@ -1746,7 +1746,7 @@ class StockItemCreate(AjaxCreateView): data = form.cleaned_data part = data.get('part', None) - + quantity = data.get('quantity', None) owner = data.get('owner', None) @@ -1831,7 +1831,7 @@ class StockItemCreate(AjaxCreateView): ) item.save(user=self.request.user) - + # Create a single StockItem of the specified quantity else: form._post_clean() @@ -1841,12 +1841,12 @@ class StockItemCreate(AjaxCreateView): item.save(user=self.request.user) return item - + # Non-trackable part else: form._post_clean() - + item = form.save(commit=False) item.user = self.request.user item.save(user=self.request.user) diff --git a/InvenTree/users/admin.py b/InvenTree/users/admin.py index d8406bfddd..91fed49830 100644 --- a/InvenTree/users/admin.py +++ b/InvenTree/users/admin.py @@ -127,7 +127,7 @@ class RoleGroupAdmin(admin.ModelAdmin): if rule_set.can_delete: permission_level = append_permission_level(permission_level, 'D') - + return permission_level def admin(self, obj): diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py index cd222cb2a2..f26a7ee64b 100644 --- a/InvenTree/users/models.py +++ b/InvenTree/users/models.py @@ -185,7 +185,7 @@ class RuleSet(models.Model): can_change = models.BooleanField(verbose_name=_('Change'), default=False, help_text=_('Permissions to edit items')) can_delete = models.BooleanField(verbose_name=_('Delete'), default=False, help_text=_('Permission to delete items')) - + @classmethod def check_table_permission(cls, user, table, permission): """ @@ -373,7 +373,7 @@ def update_group_roles(group, debug=False): # Add any required permissions to the group for perm in permissions_to_add: - + # Ignore if permission is already in the group if perm in group_permissions: continue @@ -541,7 +541,7 @@ class Owner(models.Model): pass return owner - + return owner def get_related_owners(self, include_group=False): @@ -562,7 +562,7 @@ class Owner(models.Model): Q(owner_id=self.owner.id, owner_type=ContentType.objects.get_for_model(Group).id) else: query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(user_model).id) - + related_owners = Owner.objects.filter(query) elif type(self.owner) is user_model: diff --git a/InvenTree/users/test_migrations.py b/InvenTree/users/test_migrations.py index 7e4c24b2dc..7bb17d0070 100644 --- a/InvenTree/users/test_migrations.py +++ b/InvenTree/users/test_migrations.py @@ -24,7 +24,7 @@ class TestForwardMigrations(MigratorTestCase): email='fred@fred.com', password='password' ) - + User.objects.create( username='brad', email='brad@fred.com', diff --git a/InvenTree/users/tests.py b/InvenTree/users/tests.py index 895d0a84af..e8ec6b3c74 100644 --- a/InvenTree/users/tests.py +++ b/InvenTree/users/tests.py @@ -17,7 +17,7 @@ class RuleSetModelTest(TestCase): def test_ruleset_models(self): keys = RuleSet.RULESET_MODELS.keys() - + # Check if there are any rulesets which do not have models defined missing = [name for name in RuleSet.RULESET_NAMES if name not in keys] @@ -88,7 +88,7 @@ class RuleSetModelTest(TestCase): extra_models = set() defined_models = set() - + for model in assigned_models: defined_models.add(model) @@ -198,7 +198,7 @@ class OwnerModelTest(TestCase): self.user.delete() user_as_owner = Owner.get_owner(self.user) self.assertEqual(user_as_owner, None) - + # Delete group and verify owner was deleted too self.group.delete() group_as_owner = Owner.get_owner(self.group) diff --git a/tasks.py b/tasks.py index 37cbc71eab..88bd5e42e4 100644 --- a/tasks.py +++ b/tasks.py @@ -295,7 +295,7 @@ def export_records(c, filename='data.json'): for entry in data: if "model" in entry: - + # Clear out any permissions specified for a group if entry["model"] == "auth.group": entry["fields"]["permissions"] = [] @@ -335,7 +335,7 @@ def import_records(c, filename='data.json'): for entry in data: if "model" in entry: - + # Clear out any permissions specified for a group if entry["model"] == "auth.group": entry["fields"]["permissions"] = [] @@ -370,7 +370,7 @@ def import_fixtures(c): fixtures = [ # Build model 'build', - + # Common models 'settings', From 39d4129157e9af02ba36ece6b1ddc065a7fbe6cd Mon Sep 17 00:00:00 2001 From: Matthias Mair <66015116+matmair@users.noreply.github.com> Date: Thu, 6 May 2021 12:29:58 +0200 Subject: [PATCH 088/300] chery picked all fixed trans str from #1438 (#1554) --- InvenTree/InvenTree/validators.py | 6 ++--- InvenTree/company/views.py | 2 +- InvenTree/order/models.py | 2 +- InvenTree/order/views.py | 6 ++--- InvenTree/part/views.py | 2 +- InvenTree/stock/models.py | 38 ++++++++++++++----------------- 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/InvenTree/InvenTree/validators.py b/InvenTree/InvenTree/validators.py index f8199ef20b..d5fcb8822e 100644 --- a/InvenTree/InvenTree/validators.py +++ b/InvenTree/InvenTree/validators.py @@ -74,7 +74,7 @@ def validate_build_order_reference(value): match = re.search(pattern, value) if match is None: - raise ValidationError(_('Reference must match pattern') + f" '{pattern}'") + raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern)) def validate_purchase_order_reference(value): @@ -88,7 +88,7 @@ def validate_purchase_order_reference(value): match = re.search(pattern, value) if match is None: - raise ValidationError(_('Reference must match pattern') + f" '{pattern}'") + raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern)) def validate_sales_order_reference(value): @@ -102,7 +102,7 @@ def validate_sales_order_reference(value): match = re.search(pattern, value) if match is None: - raise ValidationError(_('Reference must match pattern') + f" '{pattern}'") + raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern)) def validate_tree_name(value): diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index be7d326c36..7ba8e5e6bf 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -202,7 +202,7 @@ class CompanyImageDownloadFromURL(AjaxUpdateView): # Check for valid response code if not response.status_code == 200: - form.add_error('url', f"{_('Invalid response')}: {response.status_code}") + form.add_error('url', _('Invalid response: {code}').format(code=response.status_code)) return response.raw.decode_content = True diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index d3b09dec1e..292a5ed492 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -367,7 +367,7 @@ class PurchaseOrder(Order): stock.save() text = _("Received items") - note = f"{_('Received')} {quantity} {_('items against order')} {str(self)}" + note = _('Received {n} items against order {name}').format(n=quantity, name=str(self)) # Add a new transaction note to the newly created stock item stock.addTransactionNote(text, user, note) diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index c62a3816d5..0ffff4e340 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -1407,7 +1407,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin): except StockItem.DoesNotExist: self.form.add_error( 'serials', - _('No matching item for serial') + f" '{serial}'" + _('No matching item for serial {serial}').format(serial=serial) ) continue @@ -1417,7 +1417,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin): if not stock_item.in_stock: self.form.add_error( 'serials', - f"'{serial}' " + _("is not in stock") + _('{serial} is not in stock').format(serial=serial) ) continue @@ -1425,7 +1425,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin): if stock_item.is_allocated(): self.form.add_error( 'serials', - f"'{serial}' " + _("already allocated to an order") + _('{serial} already allocated to an order').format(serial=serial) ) continue diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index d7c68dd6a3..2cf86945d3 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -884,7 +884,7 @@ class PartImageDownloadFromURL(AjaxUpdateView): # Check for valid response code if not response.status_code == 200: - form.add_error('url', f"{_('Invalid response')}: {response.status_code}") + form.add_error('url', _('Invalid response: {code}').format(code=response.status_code)) return response.raw.decode_content = True diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 7d9520a544..7f22b7a4ef 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -198,7 +198,7 @@ class StockItem(MPTTModel): if add_note: - note = f"{_('Created new stock item for')} {str(self.part)}" + note = _('Created new stock item for {part}').format(part=str(self.part)) # This StockItem is being saved for the first time self.addTransactionNote( @@ -613,7 +613,7 @@ class StockItem(MPTTModel): item.addTransactionNote( _("Assigned to Customer"), user, - notes=_("Manually assigned to customer") + " " + customer.name, + notes=_("Manually assigned to customer {name}").format(name=customer.name), system=True ) @@ -626,9 +626,9 @@ class StockItem(MPTTModel): """ self.addTransactionNote( - _("Returned from customer") + f" {self.customer.name}", + _("Returned from customer {name}").format(name=self.customer.name), user, - notes=_("Returned to location") + f" {location.name}", + notes=_("Returned to location {loc}").format(loc=location.name), system=True ) @@ -789,7 +789,7 @@ class StockItem(MPTTModel): # Add a transaction note to the other item stock_item.addTransactionNote( - _('Installed into stock item') + ' ' + str(self.pk), + _('Installed into stock item {pk}').format(str(self.pk)), user, notes=notes, url=self.get_absolute_url() @@ -797,7 +797,7 @@ class StockItem(MPTTModel): # Add a transaction note to this item self.addTransactionNote( - _('Installed stock item') + ' ' + str(stock_item.pk), + _('Installed stock item {pk}').format(str(stock_item.pk)), user, notes=notes, url=stock_item.get_absolute_url() ) @@ -821,7 +821,7 @@ class StockItem(MPTTModel): # Add a transaction note to the parent item self.belongs_to.addTransactionNote( - _("Uninstalled stock item") + ' ' + str(self.pk), + _("Uninstalled stock item {pk}").format(pk=str(self.pk)), user, notes=notes, url=self.get_absolute_url(), @@ -840,7 +840,7 @@ class StockItem(MPTTModel): # Add a transaction note! self.addTransactionNote( - _('Uninstalled into location') + ' ' + str(location), + _('Uninstalled into location {loc}').formaT(loc=str(location)), user, notes=notes, url=url @@ -966,7 +966,7 @@ class StockItem(MPTTModel): if len(existing) > 0: exists = ','.join([str(x) for x in existing]) - raise ValidationError({"serial_numbers": _("Serial numbers already exist") + ': ' + exists}) + raise ValidationError({"serial_numbers": _("Serial numbers already exist: {exists}").format(exists=exists)}) # Create a new stock item for each unique serial number for serial in serials: @@ -1074,7 +1074,7 @@ class StockItem(MPTTModel): new_stock.addTransactionNote( _("Split from existing stock"), user, - f"{_('Split')} {helpers.normalize(quantity)} {_('items')}" + _('Split {n} items').format(n=helpers.normalize(quantity)) ) # Remove the specified quantity from THIS stock item @@ -1131,10 +1131,10 @@ class StockItem(MPTTModel): return True - msg = f"{_('Moved to')} {str(location)}" - if self.location: - msg += f" ({_('from')} {str(self.location)})" + msg = _("Moved to {loc_new} (from {loc_old})").format(loc_new=str(location), loc_old=str(self.location)) + else: + msg = _('Moved to {loc_new}').format(loc_new=str(location)) self.location = location @@ -1202,9 +1202,7 @@ class StockItem(MPTTModel): if self.updateQuantity(count): - n = helpers.normalize(count) - - text = f"{_('Counted')} {n} {_('items')}" + text = _('Counted {n} items').format(n=helpers.normalize(count)) self.addTransactionNote( text, @@ -1236,9 +1234,8 @@ class StockItem(MPTTModel): return False if self.updateQuantity(self.quantity + quantity): - - n = helpers.normalize(quantity) - text = f"{_('Added')} {n} {_('items')}" + + text = _('Added {n} items').format(n=helpers.normalize(quantity)) self.addTransactionNote( text, @@ -1268,8 +1265,7 @@ class StockItem(MPTTModel): if self.updateQuantity(self.quantity - quantity): - q = helpers.normalize(quantity) - text = f"{_('Removed')} {q} {_('items')}" + text = _('Removed {n1} items').format(n1=helpers.normalize(quantity)) self.addTransactionNote(text, user, From a77d9d9de76ec4d689f9f4acab35b666b07cfc7b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 6 May 2021 14:33:03 +0200 Subject: [PATCH 089/300] same treatment for html --- InvenTree/build/templates/build/allocate.html | 4 ++-- .../build/templates/build/build_base.html | 2 +- InvenTree/build/templates/build/index.html | 12 +++++----- InvenTree/build/templates/build/navbar.html | 2 +- InvenTree/build/templates/build/notes.html | 4 ++-- .../company/templates/company/detail.html | 2 +- .../company/manufacturer_part_delete.html | 4 ++-- .../company/manufacturer_part_detail.html | 2 +- .../company/manufacturer_part_suppliers.html | 2 +- .../company/templates/company/navbar.html | 2 +- .../company/templates/company/notes.html | 6 ++--- .../company/supplier_part_delete.html | 2 +- .../company/supplier_part_detail.html | 2 +- .../company/supplier_part_orders.html | 2 +- .../company/supplier_part_pricing.html | 2 +- .../order/templates/order/po_attachments.html | 2 +- .../order/purchase_order_detail.html | 4 ++-- .../templates/order/purchase_orders.html | 6 ++--- .../templates/order/sales_order_detail.html | 22 +++++++++---------- .../order/templates/order/sales_orders.html | 4 ++-- InvenTree/part/templates/part/build.html | 2 +- InvenTree/part/templates/part/category.html | 2 +- InvenTree/part/templates/part/detail.html | 2 +- .../part/templates/part/manufacturer.html | 2 +- InvenTree/part/templates/part/notes.html | 4 ++-- InvenTree/part/templates/part/params.html | 2 +- InvenTree/part/templates/part/part_base.html | 12 +++++----- .../part/templates/part/select_image.html | 2 +- .../part/templates/part/set_category.html | 8 +++---- .../part/templates/part/subcategory.html | 2 +- InvenTree/part/templates/part/supplier.html | 2 +- .../report/inventree_build_order_base.html | 2 +- .../report/inventree_report_base.html | 4 ++-- InvenTree/stock/templates/stock/item.html | 2 +- .../stock/templates/stock/item_base.html | 2 +- .../stock/templates/stock/item_tests.html | 2 +- InvenTree/stock/templates/stock/location.html | 10 ++++----- InvenTree/stock/templates/stock/navbar.html | 2 +- .../stock/templates/stock/stock_adjust.html | 4 ++-- .../stock/templates/stock/sublocation.html | 2 +- InvenTree/templates/InvenTree/index.html | 2 +- InvenTree/templates/InvenTree/search.html | 6 ++--- .../InvenTree/settings/category.html | 4 ++-- .../templates/InvenTree/settings/part.html | 2 +- .../InvenTree/settings/settings.html | 2 +- InvenTree/templates/base.html | 12 +++++----- InvenTree/templates/modal_form.html | 4 ++-- InvenTree/templates/modals.html | 2 +- InvenTree/templates/registration/login.html | 10 ++++----- .../registration/password_reset_done.html | 2 +- InvenTree/templates/two_column.html | 2 +- 51 files changed, 103 insertions(+), 103 deletions(-) diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html index dee90a26a0..de07614c8e 100644 --- a/InvenTree/build/templates/build/allocate.html +++ b/InvenTree/build/templates/build/allocate.html @@ -86,7 +86,7 @@ } ); }); - + $("#btn-order-parts").click(function() { launchModalForm("/order/purchase-order/order-parts/", { data: { @@ -94,7 +94,7 @@ }, }); }); - + {% endif %} {% endblock %} diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index c0f6e400b6..177fad8d6c 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -230,5 +230,5 @@ src="{% static 'img/blank_image.png' %}" } ); }); - + {% endblock %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/index.html b/InvenTree/build/templates/build/index.html index fbed17bfa3..c336ab9fc1 100644 --- a/InvenTree/build/templates/build/index.html +++ b/InvenTree/build/templates/build/index.html @@ -17,9 +17,9 @@
    - +
    - +
    @@ -66,7 +66,7 @@ + + + diff --git a/InvenTree/templates/clipboard.html b/InvenTree/templates/clipboard.html new file mode 100644 index 0000000000..e40c57a370 --- /dev/null +++ b/InvenTree/templates/clipboard.html @@ -0,0 +1,3 @@ + + + \ No newline at end of file From 9f6f69a8154176d519ef29bf0644aae108274176 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 9 May 2021 14:29:35 +0200 Subject: [PATCH 127/300] rename for shorter inclusion str --- InvenTree/templates/{clipboard.html => clip.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename InvenTree/templates/{clipboard.html => clip.html} (100%) diff --git a/InvenTree/templates/clipboard.html b/InvenTree/templates/clip.html similarity index 100% rename from InvenTree/templates/clipboard.html rename to InvenTree/templates/clip.html From d38c1f6c0b6c651ab6591cee5c130e24067f2747 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 9 May 2021 14:30:39 +0200 Subject: [PATCH 128/300] sample implementation --- InvenTree/part/templates/part/detail.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 589e4f2533..9df2f9d542 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -20,20 +20,20 @@
    - + {% if part.IPN %} - + {% endif %} {% if part.revision %} - + {% endif %} {% if part.trackable %} @@ -42,7 +42,7 @@ - + {% if part.variant_of %} @@ -96,7 +96,7 @@ {% endif %} From c148ab9f8e9b0ba8636556d382189c3f5796c452 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 9 May 2021 14:34:52 +0200 Subject: [PATCH 129/300] fixed css-comments --- InvenTree/InvenTree/static/css/inventree.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index e7b8aeb71e..99fff46447 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -568,7 +568,7 @@ } .media { - //padding-top: 15px; + /* padding-top: 15px; */ overflow: visible; } @@ -594,8 +594,8 @@ width: 160px; position: fixed; z-index: 1; - //top: 0; - //left: 0; + /* top: 0; + left: 0; */ overflow-x: hidden; padding-top: 20px; padding-right: 25px; @@ -826,7 +826,7 @@ input[type="submit"] { width: 100%; padding: 20px; z-index: 5000; - pointer-events: none; // Prevent this div from blocking links underneath + pointer-events: none; /* Prevent this div from blocking links underneath */ } .alert { From b0a8477a541a70c6e50640afdc19e4b287345503 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 9 May 2021 14:35:33 +0200 Subject: [PATCH 130/300] removes unallowed char --- InvenTree/InvenTree/static/css/inventree.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 99fff46447..544952e830 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -507,7 +507,7 @@ padding-right: 6px; padding-top: 3px; padding-bottom: 2px; -}; +} .panel-heading .badge { float: right; From d9f621c9226d1a087774362501e9ceced2098581 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 10 May 2021 12:29:51 +1000 Subject: [PATCH 131/300] Login redirect fix --- InvenTree/InvenTree/middleware.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/middleware.py b/InvenTree/InvenTree/middleware.py index f30d77ad3b..1f9aa23513 100644 --- a/InvenTree/InvenTree/middleware.py +++ b/InvenTree/InvenTree/middleware.py @@ -78,8 +78,16 @@ class AuthRequiredMiddleware(object): return HttpResponseRedirect(reverse_lazy('login')) login = reverse_lazy('login') + logout = reverse_lazy('logout') - if not request.path_info == login and not request.path_info.startswith('/api/'): + path = request.path_info + + urls = [ + login, + logout, + ] + + if path not in urls and not path.startswith('/api/') and '/admin/logout/' not in path: # Save the 'next' parameter to pass through to the login view return redirect('%s?next=%s' % (login, request.path)) From be31154a444d92496bb5c9b7502aaf53c4513959 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 10 May 2021 12:33:49 +1000 Subject: [PATCH 132/300] Cleaner implementation --- InvenTree/InvenTree/middleware.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/InvenTree/InvenTree/middleware.py b/InvenTree/InvenTree/middleware.py index 1f9aa23513..32ecd33b86 100644 --- a/InvenTree/InvenTree/middleware.py +++ b/InvenTree/InvenTree/middleware.py @@ -77,17 +77,17 @@ class AuthRequiredMiddleware(object): if request.path_info == reverse_lazy('logout'): return HttpResponseRedirect(reverse_lazy('login')) - login = reverse_lazy('login') - logout = reverse_lazy('logout') - path = request.path_info + # List of URL endpoints we *do not* want to redirect to urls = [ - login, - logout, + reverse_lazy('login'), + reverse_lazy('logout'), + reverse_lazy('admin:login'), + reverse_lazy('admin:logout'), ] - if path not in urls and not path.startswith('/api/') and '/admin/logout/' not in path: + if path not in urls and not path.startswith('/api/'): # Save the 'next' parameter to pass through to the login view return redirect('%s?next=%s' % (login, request.path)) From 7e55e343e2cb0d90fb392abaa6e837984b357d4a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 10 May 2021 12:35:19 +1000 Subject: [PATCH 133/300] PEP fix --- InvenTree/InvenTree/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/middleware.py b/InvenTree/InvenTree/middleware.py index 32ecd33b86..b905e86795 100644 --- a/InvenTree/InvenTree/middleware.py +++ b/InvenTree/InvenTree/middleware.py @@ -90,7 +90,7 @@ class AuthRequiredMiddleware(object): if path not in urls and not path.startswith('/api/'): # Save the 'next' parameter to pass through to the login view - return redirect('%s?next=%s' % (login, request.path)) + return redirect('%s?next=%s' % (reverse_lazy('login'), request.path)) # Code to be executed for each request/response after # the view is called. From fc83458bdb192fafa0d758cbb82acedd3d974d33 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 10 May 2021 07:53:58 +0200 Subject: [PATCH 134/300] changes as suggested by @SchrodingersGat --- InvenTree/InvenTree/static/css/inventree.css | 1 - InvenTree/templates/clip.html | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index d90b29afc2..26720f360f 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -946,6 +946,5 @@ input[type="date"].form-control, input[type="time"].form-control, input[type="da } .clip-btn:hover { - padding: 6px 6px; background: var(--label-grey); } diff --git a/InvenTree/templates/clip.html b/InvenTree/templates/clip.html index e40c57a370..a56ece838c 100644 --- a/InvenTree/templates/clip.html +++ b/InvenTree/templates/clip.html @@ -1,3 +1,5 @@ +{% load i18n %} + - + \ No newline at end of file From 6aab704144bba00ffc5dd759b3e17265c5998c14 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 10 May 2021 19:40:54 +1000 Subject: [PATCH 135/300] Trim content when copying to clipboard --- .../static/script/inventree/inventree.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/InvenTree/InvenTree/static/script/inventree/inventree.js b/InvenTree/InvenTree/static/script/inventree/inventree.js index 0c5cd2426c..b3209ca267 100644 --- a/InvenTree/InvenTree/static/script/inventree/inventree.js +++ b/InvenTree/InvenTree/static/script/inventree/inventree.js @@ -1,3 +1,14 @@ +function attachClipboard(selector) { + + new ClipboardJS(selector, { + text: function(trigger) { + var content = trigger.parentElement.parentElement.textContent; + + return content.trim(); + } + }); +} + function inventreeDocReady() { /* Run this function when the HTML document is loaded. * This will be called for every page that extends "base.html" @@ -50,11 +61,8 @@ function inventreeDocReady() { }); // Initialize clipboard-buttons - new ClipboardJS('.clip-btn', { - text: function(trigger) { - return trigger.parentElement.parentElement.textContent; - } - }); + attachClipboard('.clip-btn'); + } function isFileTransfer(transfer) { From f0932040ee9d6129aa531a23798907cc3ff9d75d Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 10 May 2021 11:42:22 -0400 Subject: [PATCH 136/300] Fixed form validation for previous step, hide tab depending on order status, added purchase_price field --- InvenTree/common/files.py | 5 +- InvenTree/common/forms.py | 33 +++++++++++- InvenTree/common/views.py | 29 ++++++----- .../order/order_wizard/match_parts.html | 8 ++- .../order/order_wizard/po_upload.html | 6 +++ .../order/templates/order/po_navbar.html | 3 ++ InvenTree/order/views.py | 50 ++++++++++++++++--- 7 files changed, 111 insertions(+), 23 deletions(-) diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py index 91fdc61a10..1a4de55cb9 100644 --- a/InvenTree/common/files.py +++ b/InvenTree/common/files.py @@ -102,8 +102,9 @@ class FileManager: ] self.OPTIONAL_HEADERS = [ - 'Unit_Price', - 'Extended_Price', + 'Purchase_Price', + 'Reference', + 'Notes', ] # Update headers diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index 63ed74c378..ba844c3651 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -8,6 +8,8 @@ from __future__ import unicode_literals from django import forms from django.utils.translation import gettext as _ +from djmoney.forms.fields import MoneyField + from InvenTree.forms import HelperForm from .files import FileManager @@ -121,6 +123,7 @@ class MatchItem(forms.Form): for row in row_data: # Navigate column data for col in row['data']: + # Create input for required headers if col['column']['guess'] in file_manager.REQUIRED_HEADERS: # Set field name @@ -156,11 +159,37 @@ class MatchItem(forms.Form): # Set field select box self.fields[field_name] = forms.ChoiceField( choices=[('', '-' * 10)] + item_options, - required=True, + required=False, widget=forms.Select(attrs={ 'class': 'select bomselect', }) ) - # Update initial selection + # Update select box when match was found if item_match: + # Make it a required field + self.fields[field_name].required = True + # Update initial value self.fields[field_name].initial = item_match.id + + # Optional entries + elif col['column']['guess'] in file_manager.OPTIONAL_HEADERS: + # Set field name + field_name = col['column']['guess'].lower() + '-' + str(row['index']) + # Get value + value = row.get(col['column']['guess'].lower(), '') + # Set field input box + if 'price' in col['column']['guess'].lower(): + self.fields[field_name] = MoneyField( + label=_(col['column']['guess']), + default_currency='USD', + decimal_places=5, + max_digits=19, + required=False, + default_amount=value, + ) + else: + self.fields[field_name] = forms.Input( + required=True, + widget=forms.Select(attrs={ + }) + ) diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 6186732ff2..3ebc18f5c4 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -191,6 +191,7 @@ class FileManagementFormView(MultiStepFormView): # Set keys for item matching key_item_select = 'item_select' key_quantity_select = 'quantity' + key_price_select = 'price' def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -314,6 +315,19 @@ class FileManagementFormView(MultiStepFormView): self.column_selections[col_name] = value def set_form_table_data(self, form=None): + """ Set the form table data """ + + if self.column_names: + # Re-construct the column data + self.columns = [] + + for key in self.column_names: + header = ({ + 'name': key, + 'guess': self.column_selections.get(key, ''), + }) + self.columns.append(header) + if self.row_data: # Re-construct the row data self.rows = [] @@ -323,12 +337,12 @@ class FileManagementFormView(MultiStepFormView): items = [] for col_idx in sorted(row.keys()): - value = row[col_idx] items.append(value) self.rows.append({ 'index': row_idx, + 'column': self.columns[row_idx], 'data': items, 'errors': {}, }) @@ -370,17 +384,8 @@ class FileManagementFormView(MultiStepFormView): row['item_select'] = self.key_item_select + '-' + str(row['index']) # Add quantity select field row['quantity_select'] = self.key_quantity_select + '-' + str(row['index']) - - if self.column_names: - # Re-construct the column data - self.columns = [] - - for key in self.column_names: - header = ({ - 'name': key, - 'guess': self.column_selections.get(key, ''), - }) - self.columns.append(header) + # Add price select field + row['price_select'] = self.key_price_select + '-' + str(row['index']) def get_column_index(self, name): """ Return the index of the column with the given name. diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index aa9776085f..0808ac4259 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -48,7 +48,7 @@ - + {% for col in form %} - + {% for col in form %} {% for row in rows %} - {% with forloop.counter as row_index %} + {% with forloop.counter0 as row_index %} - - + {% for item in row.data %} {% endfor %} diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index 6cfcd334f3..18e984408f 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -4,6 +4,8 @@ {% load static %} {% block form_alert %} +{% if form.errors %} +{% endif %} {% if form_errors %} - + {% for col in columns %} + {% if col.name != 'Quantity' %} + {% endif %} {% endfor %} @@ -42,13 +46,12 @@ {% for row in rows %} - - {% for item in row.data %} + {% for item in row.data %} + {% if item.column.guess != 'Quantity' %} + + {% endif %} {% endfor %} {% endfor %} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index dbc45ba5ea..28cc355ffa 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -651,8 +651,8 @@ class PurchaseOrderUpload(FileManagementFormView): except (ValueError, SupplierPart.DoesNotExist, SupplierPart.MultipleObjectsReturned): exact_match_part = None - # Check if there is a column corresponding to "Manufacturer MPN" - if m_idx >= 0: + # Check if there is a column corresponding to "Manufacturer MPN" and no exact match found yet + if m_idx >= 0 and not exact_match_part: mpn = row['data'][m_idx]['cell'] try: @@ -755,7 +755,7 @@ class PurchaseOrderUpload(FileManagementFormView): order=order, part=supplier_part, quantity=purchase_order_item['quantity'], - purchase_price=purchase_order_item['purchase_price'], + purchase_price=purchase_order_item.get('purchase_price', None), ) try: purchase_order_line_item.save() From 82c6d10c3368294d011fe1f61a275104f7c8ef12 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 17:11:07 +1000 Subject: [PATCH 139/300] Add translateable status codes for StockHistory --- InvenTree/InvenTree/status_codes.py | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index c73ef10018..53b747a9ad 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -224,6 +224,82 @@ class StockStatus(StatusCode): ] +class StockHistoryCode(StatusCode): + + LEGACY = 0 + + CREATED = 1 + + # Manual editing operations + EDITED = 5 + ASSIGNED_SERIAL = 6 + + # Manual stock operations + STOCK_COUNT = 10 + STOCK_ADD = 11 + STOCK_REMOVE = 12 + + # Location operations + STOCK_MOVE = 20 + + # Installation operations + INSTALLED_INTO_ASSEMBLY = 30 + REMOVED_FROM_ASSEMBLY = 31 + + INSTALLED_CHILD_ITEM = 35 + REMOVED_CHILD_ITEM = 36 + + # Stock splitting operations + SPLIT_FROM_PARENT = 40 + SPLIT_CHILD_ITEM = 42 + + # Build order codes + BUILD_OUTPUT_CREATED = 50 + BUILD_OUTPUT_COMPLETED = 55 + + # Sales order codes + + # Purchase order codes + RECEIVED_AGAINST_PURCHASE_ORDER = 70 + + # Customer actions + SENT_TO_CUSTOMER = 100 + RETURNED_FROM_CUSTOMER = 105 + + options = { + LEGACY: _('Legacy stock tracking entry'), + + CREATED: _('Stock item created'), + + EDITED: _('Edited stock item'), + ASSIGNED_SERIAL: _('Assigned serial number'), + + STOCK_COUNT: _('Stock counted'), + STOCK_ADD: _('Stock manually added'), + STOCK_REMOVE: _('Stock manually removed'), + + STOCK_MOVE: _('Location changed'), + + INSTALLED_INTO_ASSEMBLY: _('Installed into assembly'), + REMOVED_FROM_ASSEMBLY: _('Removed from assembly'), + + INSTALLED_CHILD_ITEM: _('Installed component item'), + REMOVED_CHILD_ITEM: _('Removed component item'), + + SPLIT_FROM_PARENT: _('Split from parent item'), + SPLIT_CHILD_ITEM: _('Split child item'), + + SENT_TO_CUSTOMER: _('Sent to customer'), + RETURNED_FROM_CUSTOMER: _('Returned from customer'), + + BUILD_OUTPUT_CREATED: _('Build order output created'), + BUILD_OUTPUT_COMPLETED: _('Build order output completed'), + + RECEIVED_AGAINST_PURCHASE_ORDER: _('Received against purchase order') + + } + + class BuildStatus(StatusCode): # Build status codes From af53b341f002e981ee3cb9da4e9f0e0d187d45a3 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 17:17:48 +1000 Subject: [PATCH 140/300] Replace "addTrasactionNote" function with "add_tracking_entry" - Does not add translated strings to the database --- InvenTree/build/models.py | 12 +- InvenTree/order/models.py | 24 +- .../migrations/0060_auto_20210511_1713.py | 28 ++ .../migrations/0061_auto_20210511_0911.py | 59 ++++ InvenTree/stock/models.py | 272 ++++++++++++------ 5 files changed, 299 insertions(+), 96 deletions(-) create mode 100644 InvenTree/stock/migrations/0060_auto_20210511_1713.py create mode 100644 InvenTree/stock/migrations/0061_auto_20210511_0911.py diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index a278b4e17c..c80c0e8523 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -22,7 +22,7 @@ from markdownx.models import MarkdownxField from mptt.models import MPTTModel, TreeForeignKey -from InvenTree.status_codes import BuildStatus, StockStatus +from InvenTree.status_codes import BuildStatus, StockStatus, StockHistoryCode from InvenTree.helpers import increment, getSetting, normalize, MakeBarcode from InvenTree.validators import validate_build_order_reference from InvenTree.models import InvenTreeAttachment @@ -811,6 +811,7 @@ class Build(MPTTModel): # Select the location for the build output location = kwargs.get('location', self.destination) status = kwargs.get('status', StockStatus.OK) + notes = kwargs.get('notes', '') # List the allocated BuildItem objects for the given output allocated_items = output.items_to_install.all() @@ -834,10 +835,13 @@ class Build(MPTTModel): output.save() - output.addTransactionNote( - _('Completed build output'), + output.add_tracking_entry( + StockHistoryCode.BUILD_OUTPUT_COMPLETED, user, - system=True + notes=notes, + deltas={ + 'status': status, + } ) # Increase the completed quantity for this build diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 534775ebaf..8572d0c634 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -28,7 +28,7 @@ from company.models import Company, SupplierPart from InvenTree.fields import RoundingDecimalField from InvenTree.helpers import decimal2string, increment, getSetting -from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus +from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus, StockHistoryCode from InvenTree.models import InvenTreeAttachment @@ -336,10 +336,12 @@ class PurchaseOrder(Order): return self.pending_line_items().count() == 0 @transaction.atomic - def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None): + def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None, **kwargs): """ Receive a line item (or partial line item) against this PO """ + notes = kwargs.get('notes', '') + if not self.status == PurchaseOrderStatus.PLACED: raise ValidationError({"status": _("Lines can only be received against an order marked as 'Placed'")}) @@ -369,8 +371,22 @@ class PurchaseOrder(Order): text = _("Received items") note = _('Received {n} items against order {name}').format(n=quantity, name=str(self)) - # Add a new transaction note to the newly created stock item - stock.addTransactionNote(text, user, note) + tracking_info = { + 'status': status, + 'purchaseorder': self.pk, + 'quantity': quantity, + } + + if location: + tracking_info['location'] = location.pk + + stock.add_tracking_entry( + StockHistoryCode.RECEIVED_AGAINST_PURCHASE_ORDER, + user, + notes=notes, + url=self.get_absolute_url(), + deltas=tracking_info + ) # Update the number of parts received against the particular line item line.received += quantity diff --git a/InvenTree/stock/migrations/0060_auto_20210511_1713.py b/InvenTree/stock/migrations/0060_auto_20210511_1713.py new file mode 100644 index 0000000000..752b070750 --- /dev/null +++ b/InvenTree/stock/migrations/0060_auto_20210511_1713.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2 on 2021-05-11 07:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0059_auto_20210404_2016'), + ] + + operations = [ + migrations.AddField( + model_name='stockitemtracking', + name='deltas', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='stockitemtracking', + name='tracking_type', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='stockitemtracking', + name='title', + field=models.CharField(blank=True, help_text='Tracking entry title', max_length=250, verbose_name='Title'), + ), + ] diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py new file mode 100644 index 0000000000..087863c348 --- /dev/null +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2 on 2021-05-10 23:11 + +from django.db import migrations + + +def update_history(apps, schema_editor): + """ + Update each existing StockItemTracking object, + convert the recorded "quantity" to a delta + """ + + StockItem = apps.get_model('stock', 'stockitem') + StockItemTracking = apps.get_model('stock', 'stockitemtracking') + + update_count = 0 + + for item in StockItem.objects.all(): + + history = StockItemTracking.objects.filter(item=item).order_by('date') + + if history.count() == 0: + continue + + quantity = history[0].quantity + + for entry in history: + + q = entry.quantity + + if not q == quantity: + + entry.deltas = { + 'quantity': float(q), + } + + entry.save() + + update_count += 1 + + quantity = q + + print(f"Updated {update_count} StockItemHistory entries") + + +def reverse_update(apps, schema_editor): + """ + """ + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0060_auto_20210511_1713'), + ] + + operations = [ + migrations.RunPython(update_history, reverse_code=reverse_update) + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 3aecfff2c2..408c598141 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -34,7 +34,7 @@ import common.models import report.models import label.models -from InvenTree.status_codes import StockStatus +from InvenTree.status_codes import StockStatus, StockHistoryCode from InvenTree.models import InvenTreeTree, InvenTreeAttachment from InvenTree.fields import InvenTreeURLField @@ -198,14 +198,18 @@ class StockItem(MPTTModel): if add_note: - note = _('Created new stock item for {part}').format(part=str(self.part)) + tracking_info = { + 'quantity': self.quantity, + 'status': self.status, + } - # This StockItem is being saved for the first time - self.addTransactionNote( - _('Created stock item'), + if self.location: + tracking_info['location'] = self.location.pk + + self.add_tracking_entry( + StockHistoryCode.CREATED, user, - note, - system=True + deltas=tracking_info ) @property @@ -610,31 +614,45 @@ class StockItem(MPTTModel): # TODO - Remove any stock item allocations from this stock item - item.addTransactionNote( - _("Assigned to Customer"), + item.add_tracking_entry( + StockHistoryCode.SENT_TO_CUSTOMER, user, - notes=_("Manually assigned to customer {name}").format(name=customer.name), - system=True + { + 'customer': customer.id, + 'customer_name': customer.name, + }, + notes=notes, ) # Return the reference to the stock item return item - def returnFromCustomer(self, location, user=None): + def returnFromCustomer(self, location, user=None, **kwargs): """ Return stock item from customer, back into the specified location. """ - self.addTransactionNote( - _("Returned from customer {name}").format(name=self.customer.name), + notes = kwargs.get('notes', '') + + tracking_info = {} + + if location: + tracking_info['location'] = location.id + tracking_info['location_name'] = location.name + + if self.customer: + tracking_info['customer'] = customer.id + tracking_info['customer_name'] = customer.name + + self.add_tracking_entry( + StockHistoryCode.RETURNED_FROM_CUSTOMER, user, - notes=_("Returned to location {loc}").format(loc=location.name), - system=True + notes=notes, + deltas=tracking_info ) self.customer = None self.location = location - self.sales_order = None self.save() @@ -788,18 +806,25 @@ class StockItem(MPTTModel): stock_item.save() # Add a transaction note to the other item - stock_item.addTransactionNote( - _('Installed into stock item {pk}').format(str(self.pk)), + stock_item.add_tracking_entry( + StockHistoryCode.INSTALLED_INTO_ASSEMBLY, user, notes=notes, - url=self.get_absolute_url() + url=self.get_absolute_url(), + deltas={ + 'assembly': self.pk, + } ) - # Add a transaction note to this item - self.addTransactionNote( - _('Installed stock item {pk}').format(str(stock_item.pk)), - user, notes=notes, - url=stock_item.get_absolute_url() + # Add a transaction note to this item (the assembly) + self.add_tracking_entry( + StockHistoryCode.INSTALLED_CHILD_ITEM, + user, + notes=notes, + url=stock_item.get_absolute_url(), + deltas={ + 'stockitem': stock_item.pk, + } ) @transaction.atomic @@ -820,32 +845,41 @@ class StockItem(MPTTModel): # TODO - Are there any other checks that need to be performed at this stage? # Add a transaction note to the parent item - self.belongs_to.addTransactionNote( - _("Uninstalled stock item {pk}").format(pk=str(self.pk)), + self.belongs_to.add_tracking_entry( + StockHistoryCode.REMOVED_CHILD_ITEM, user, + deltas={ + 'stockitem': self.pk, + }, notes=notes, url=self.get_absolute_url(), ) + tracking_info = { + 'assembly': self.belongs_to.pk + } + + if location: + tracking_info['location'] = location.pk + tracking_info['location_name'] = location.name + url = location.get_absolute_url() + else: + url = '' + + self.add_tracking_entry( + StockHistoryCode.REMOVED_FROM_ASSEMBLY, + user, + notes=notes, + url=url, + deltas=tracking_info + ) + # Mark this stock item as *not* belonging to anyone self.belongs_to = None self.location = location self.save() - if location: - url = location.get_absolute_url() - else: - url = '' - - # Add a transaction note! - self.addTransactionNote( - _('Uninstalled into location {loc}').formaT(loc=str(location)), - user, - notes=notes, - url=url - ) - @property def children(self): """ Return a list of the child items which have been split from this stock item """ @@ -901,24 +935,30 @@ class StockItem(MPTTModel): def has_tracking_info(self): return self.tracking_info_count > 0 - def addTransactionNote(self, title, user, notes='', url='', system=True): - """ Generation a stock transaction note for this item. + def add_tracking_entry(self, entry_type, user, deltas={}, notes='', url=''): + """ + Add a history tracking entry for this StockItem - Brief automated note detailing a movement or quantity change. + Args: + entry_type - Integer code describing the "type" of historical action (see StockHistoryCode) + user - The user performing this action + deltas - A map of the changes made to the model + notes - User notes associated with this tracking entry + url - Optional URL associated with this tracking entry """ - track = StockItemTracking.objects.create( + entry = StockItemTracking.objects.create( item=self, - title=title, + tracking_type=entry_type, user=user, - quantity=self.quantity, - date=datetime.now().date(), + date=datetime.now(), notes=notes, + deltas=deltas, link=url, - system=system + system=True ) - track.save() + entry.save() @transaction.atomic def serializeStock(self, quantity, serials, user, notes='', location=None): @@ -991,10 +1031,17 @@ class StockItem(MPTTModel): new_item.copyTestResultsFrom(self) # Create a new stock tracking item - new_item.addTransactionNote(_('Add serial number'), user, notes=notes) + new_item.add_tracking_entry( + StockHistoryCode.ASSIGNED_SERIAL, + user, + notes=notes, + deltas={ + 'serial': serial, + } + ) # Remove the equivalent number of items - self.take_stock(quantity, user, notes=_('Serialized {n} items').format(n=quantity)) + self.take_stock(quantity, user, notes=notes) @transaction.atomic def copyHistoryFrom(self, other): @@ -1018,7 +1065,7 @@ class StockItem(MPTTModel): result.save() @transaction.atomic - def splitStock(self, quantity, location, user): + def splitStock(self, quantity, location, user, **kwargs): """ Split this stock item into two items, in the same location. Stock tracking notes for this StockItem will be duplicated, and added to the new StockItem. @@ -1032,6 +1079,8 @@ class StockItem(MPTTModel): The new item will have a different StockItem ID, while this will remain the same. """ + notes = kwargs.get('notes', '') + # Do not split a serialized part if self.serialized: return self @@ -1071,17 +1120,20 @@ class StockItem(MPTTModel): new_stock.copyTestResultsFrom(self) # Add a new tracking item for the new stock item - new_stock.addTransactionNote( - _("Split from existing stock"), + new_stock.add_tracking_entry( + StockHistoryCode.SPLIT_FROM_PARENT, user, - _('Split {n} items').format(n=helpers.normalize(quantity)) + notes=notes, + deltas={ + 'stockitem': self.pk, + } ) # Remove the specified quantity from THIS stock item self.take_stock( quantity, user, - f"{_('Split')} {quantity} {_('items into new stock item')}" + notes=notes ) # Return a copy of the "new" stock item @@ -1138,11 +1190,21 @@ class StockItem(MPTTModel): self.location = location - self.addTransactionNote( - msg, + tracking_info = {} + + if location: + tracking_info['location'] = location.pk + url = location.get_absolute_url() + else: + url = '' + + self.add_tracking_entry( + StockHistoryCode.STOCK_MOVE, user, notes=notes, - system=True) + deltas=tracking_info, + url=url, + ) self.save() @@ -1202,13 +1264,13 @@ class StockItem(MPTTModel): if self.updateQuantity(count): - text = _('Counted {n} items').format(n=helpers.normalize(count)) - - self.addTransactionNote( - text, + self.add_tracking_entry( + StockHistoryCode.STOCK_COUNT, user, notes=notes, - system=True + deltas={ + 'quantity': self.quantity, + } ) return True @@ -1234,13 +1296,15 @@ class StockItem(MPTTModel): return False if self.updateQuantity(self.quantity + quantity): - text = _('Added {n} items').format(n=helpers.normalize(quantity)) - self.addTransactionNote( - text, + self.add_tracking_entry( + StockHistoryCode.STOCK_ADD, user, notes=notes, - system=True + deltas={ + 'added': quantity, + 'quantity': self.quantity + } ) return True @@ -1264,12 +1328,15 @@ class StockItem(MPTTModel): if self.updateQuantity(self.quantity - quantity): - text = _('Removed {n1} items').format(n1=helpers.normalize(quantity)) - - self.addTransactionNote(text, - user, - notes=notes, - system=True) + self.add_tracking_entry( + StockHistoryCode.STOCK_REMOVE, + user, + notes=notes, + deltas={ + 'removed': quantity, + 'quantity': self.quantity, + } + ) return True @@ -1527,30 +1594,57 @@ class StockItemAttachment(InvenTreeAttachment): class StockItemTracking(models.Model): - """ Stock tracking entry - breacrumb for keeping track of automated stock transactions + """ + Stock tracking entry - used for tracking history of a particular StockItem + + Note: 2021-05-11 + The legacy StockTrackingItem model contained very litle information about the "history" of the item. + In fact, only the "quantity" of the item was recorded at each interaction. + Also, the "title" was translated at time of generation, and thus was not really translateable. + The "new" system tracks all 'delta' changes to the model, + and tracks change "type" which can then later be translated + Attributes: - item: Link to StockItem + item: ForeignKey reference to a particular StockItem date: Date that this tracking info was created - title: Title of this tracking info (generated by system) + title: Title of this tracking info (legacy, no longer used!) + tracking_type: The type of tracking information notes: Associated notes (input by user) link: Optional URL to external page user: The user associated with this tracking info + deltas: The changes associated with this history item quantity: The StockItem quantity at this point in time """ def get_absolute_url(self): return '/stock/track/{pk}'.format(pk=self.id) - # return reverse('stock-tracking-detail', kwargs={'pk': self.id}) - item = models.ForeignKey(StockItem, on_delete=models.CASCADE, - related_name='tracking_info') + tracking_type = models.IntegerField( + default=StockHistoryCode.LEGACY, + ) + + item = models.ForeignKey( + StockItem, + on_delete=models.CASCADE, + related_name='tracking_info' + ) date = models.DateTimeField(auto_now_add=True, editable=False) - title = models.CharField(blank=False, max_length=250, verbose_name=_('Title'), help_text=_('Tracking entry title')) + title = models.CharField( + blank=True, + max_length=250, + verbose_name=_('Title'), + help_text=_('Tracking entry title') + ) - notes = models.CharField(blank=True, max_length=512, verbose_name=_('Notes'), help_text=_('Entry notes')) + notes = models.CharField( + blank=True, + max_length=512, + verbose_name=_('Notes'), + help_text=_('Entry notes') + ) link = InvenTreeURLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page for further information')) @@ -1558,13 +1652,15 @@ class StockItemTracking(models.Model): system = models.BooleanField(default=False) - quantity = models.DecimalField(max_digits=15, decimal_places=5, validators=[MinValueValidator(0)], default=1, verbose_name=_('Quantity')) + deltas = models.JSONField(null=True, blank=True) - # TODO - # image = models.ImageField(upload_to=func, max_length=255, null=True, blank=True) - - # TODO - # file = models.FileField() + quantity = models.DecimalField( + max_digits=15, + decimal_places=5, + validators=[MinValueValidator(0)], + default=1, + verbose_name=_('Quantity') + ) def rename_stock_item_test_result_attachment(instance, filename): From 70ad0ba0ded70cdaa5b11748e2c7f1be39d4d68f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 17:41:17 +1000 Subject: [PATCH 141/300] Improve reporting in stock history API --- InvenTree/order/models.py | 3 --- InvenTree/stock/admin.py | 2 +- InvenTree/stock/api.py | 2 +- InvenTree/stock/models.py | 7 +++++++ InvenTree/stock/serializers.py | 11 +++++++++-- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 8572d0c634..9a521b8044 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -368,9 +368,6 @@ class PurchaseOrder(Order): stock.save() - text = _("Received items") - note = _('Received {n} items against order {name}').format(n=quantity, name=str(self)) - tracking_info = { 'status': status, 'purchaseorder': self.pk, diff --git a/InvenTree/stock/admin.py b/InvenTree/stock/admin.py index 9fed3e53a4..f32fa008a0 100644 --- a/InvenTree/stock/admin.py +++ b/InvenTree/stock/admin.py @@ -130,7 +130,7 @@ class StockAttachmentAdmin(admin.ModelAdmin): class StockTrackingAdmin(ImportExportModelAdmin): - list_display = ('item', 'date', 'title') + list_display = ('item', 'date', 'label') class StockItemTestResultAdmin(admin.ModelAdmin): diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index b70b379e69..c7914827e7 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -965,7 +965,7 @@ class StockItemTestResultList(generics.ListCreateAPIView): test_result.save() -class StockTrackingList(generics.ListCreateAPIView): +class StockTrackingList(generics.ListAPIView): """ API endpoint for list view of StockItemTracking objects. StockItemTracking objects are read-only diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 408c598141..7d55d26f4d 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1620,6 +1620,13 @@ class StockItemTracking(models.Model): def get_absolute_url(self): return '/stock/track/{pk}'.format(pk=self.id) + def label(self): + + if self.tracking_type in StockHistoryCode.keys(): + return StockHistoryCode.label(self.tracking_type) + else: + return self.title + tracking_type = models.IntegerField( default=StockHistoryCode.LEGACY, ) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 4991a44e6f..c5ad3c7100 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -351,10 +351,14 @@ class StockTrackingSerializer(InvenTreeModelSerializer): url = serializers.CharField(source='get_absolute_url', read_only=True) + label = serializers.CharField(read_only=True) + item_detail = StockItemSerializerBrief(source='item', many=False, read_only=True) user_detail = UserSerializerBrief(source='user', many=False, read_only=True) + deltas = serializers.JSONField(read_only=True) + class Meta: model = StockItemTracking fields = [ @@ -363,10 +367,13 @@ class StockTrackingSerializer(InvenTreeModelSerializer): 'item', 'item_detail', 'date', - 'title', - 'notes', + 'deltas', + 'label', 'link', + 'notes', 'quantity', + 'title', + 'tracking_type', 'user', 'user_detail', 'system', From 1126e2e1106625c7c25e9ad932e5648bc1418a13 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 17:41:37 +1000 Subject: [PATCH 142/300] "Guess" stock history code from recorded title string --- .../migrations/0061_auto_20210511_0911.py | 66 +++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py index 087863c348..0a11fe1fae 100644 --- a/InvenTree/stock/migrations/0061_auto_20210511_0911.py +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -2,6 +2,8 @@ from django.db import migrations +from InvenTree.status_codes import StockHistoryCode + def update_history(apps, schema_editor): """ @@ -24,6 +26,8 @@ def update_history(apps, schema_editor): quantity = history[0].quantity for entry in history: + + updated = False q = entry.quantity @@ -33,13 +37,67 @@ def update_history(apps, schema_editor): 'quantity': float(q), } - entry.save() - - update_count += 1 + updated = True quantity = q - print(f"Updated {update_count} StockItemHistory entries") + # Try to "guess" the "type" of tracking entry, based on the title + title = entry.title.lower() + + tracking_type = None + + if 'completed build' in title: + tracking_type = StockHistoryCode.BUILD_OUTPUT_COMPLETED + + elif 'removed' in title and 'item' in title: + tracking_type = StockHistoryCode.STOCK_REMOVE + + elif 'split from existing' in title: + tracking_type = StockHistoryCode.SPLIT_FROM_PARENT + + elif 'moved to' in title: + tracking_type = StockHistoryCode.STOCK_MOVE + + elif 'created stock item' in title: + tracking_type = StockHistoryCode.CREATED + + elif 'add serial number' in title: + tracking_type = StockHistoryCode.ASSIGNED_SERIAL + + elif 'returned from customer' in title: + tracking_type = StockHistoryCode.RETURNED_FROM_CUSTOMER + + elif 'counted' in title: + tracking_type = StockHistoryCode.STOCK_COUNT + + elif 'added' in title: + tracking_type = StockHistoryCode.STOCK_ADD + + elif 'assigned to customer' in title: + tracking_type = StockHistoryCode.SENT_TO_CUSTOMER + + elif 'installed into stock item' in title: + tracking_type = StockHistoryCode.INSTALLED_INTO_ASSEMBLY + + elif 'uninstalled into location' in title: + tracking_type = StockHistoryCode.REMOVED_FROM_ASSEMBLY + + elif 'installed stock item' in title: + tracking_type = StockHistoryCode.INSTALLED_CHILD_ITEM + + elif 'received items' in title: + tracking_type = StockHistoryCode.RECEIVED_AGAINST_PURCHASE_ORDER + + if tracking_type is not None: + entry.tracking_type = tracking_type + updated = True + + if updated: + entry.save() + update_count += 1 + + + print(f"\n==========================\nUpdated {update_count} StockItemHistory entries") def reverse_update(apps, schema_editor): From 725a64c29dff06950298762124e6b8e49743cecd Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 18:11:27 +1000 Subject: [PATCH 143/300] Extract more information from legacy tracking data --- .../migrations/0061_auto_20210511_0911.py | 43 +++++++++++++++++-- InvenTree/stock/serializers.py | 6 +-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py index 0a11fe1fae..b3bcb5b88e 100644 --- a/InvenTree/stock/migrations/0061_auto_20210511_0911.py +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -1,5 +1,7 @@ # Generated by Django 3.2 on 2021-05-10 23:11 +import re + from django.db import migrations from InvenTree.status_codes import StockHistoryCode @@ -27,17 +29,19 @@ def update_history(apps, schema_editor): for entry in history: + deltas = {} updated = False q = entry.quantity if not q == quantity: - entry.deltas = { - 'quantity': float(q), - } + try: + deltas['quantity']: float(q) + updated = True + except: + print(f"WARNING: Error converting quantity '{q}'") - updated = True quantity = q @@ -51,6 +55,21 @@ def update_history(apps, schema_editor): elif 'removed' in title and 'item' in title: tracking_type = StockHistoryCode.STOCK_REMOVE + + # Extract the number of removed items + result = re.search("^removed ([\d\.]+) items$", title) + + if result: + + removed = result.groups()[0] + + try: + deltas['removed'] = float(removed) + + # Ensure that 'quantity' is stored too in this case + deltas['quantity'] = float(q) + except: + print(f"WARNING: Error converting removed quantity '{removed}'") elif 'split from existing' in title: tracking_type = StockHistoryCode.SPLIT_FROM_PARENT @@ -73,6 +92,21 @@ def update_history(apps, schema_editor): elif 'added' in title: tracking_type = StockHistoryCode.STOCK_ADD + # Extract the number of added items + result = re.search("^added ([\d\.]+) items$", title) + + if result: + + added = result.groups()[0] + + try: + deltas['added'] = float(added) + + # Ensure that 'quantity' is stored too in this case + deltas['quantity'] = float(q) + except: + print(f"WARNING: Error converting added quantity '{added}'") + elif 'assigned to customer' in title: tracking_type = StockHistoryCode.SENT_TO_CUSTOMER @@ -93,6 +127,7 @@ def update_history(apps, schema_editor): updated = True if updated: + entry.deltas = deltas entry.save() update_count += 1 diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index c5ad3c7100..d46dc7b3dc 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -349,8 +349,6 @@ class StockTrackingSerializer(InvenTreeModelSerializer): if user_detail is not True: self.fields.pop('user_detail') - url = serializers.CharField(source='get_absolute_url', read_only=True) - label = serializers.CharField(read_only=True) item_detail = StockItemSerializerBrief(source='item', many=False, read_only=True) @@ -363,7 +361,6 @@ class StockTrackingSerializer(InvenTreeModelSerializer): model = StockItemTracking fields = [ 'pk', - 'url', 'item', 'item_detail', 'date', @@ -376,7 +373,6 @@ class StockTrackingSerializer(InvenTreeModelSerializer): 'tracking_type', 'user', 'user_detail', - 'system', ] read_only_fields = [ @@ -384,4 +380,6 @@ class StockTrackingSerializer(InvenTreeModelSerializer): 'user', 'system', 'quantity', + 'label', + 'tracking_type', ] From ed4da4d3380f5fea7de037a51ef8d778f2de15d4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 18:23:29 +1000 Subject: [PATCH 144/300] Improve introspection in migration file --- .../stock/migrations/0061_auto_20210511_0911.py | 17 ++++++++++++++--- InvenTree/stock/models.py | 11 +++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py index b3bcb5b88e..2c264aac1d 100644 --- a/InvenTree/stock/migrations/0061_auto_20210511_0911.py +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -54,10 +54,14 @@ def update_history(apps, schema_editor): tracking_type = StockHistoryCode.BUILD_OUTPUT_COMPLETED elif 'removed' in title and 'item' in title: - tracking_type = StockHistoryCode.STOCK_REMOVE + + if entry.notes.lower().startswith('split '): + tracking_type = StockHistoryCode.SPLIT_CHILD_ITEM + else: + tracking_type = StockHistoryCode.STOCK_REMOVE # Extract the number of removed items - result = re.search("^removed ([\d\.]+) items$", title) + result = re.search("^removed ([\d\.]+) items", title) if result: @@ -70,9 +74,13 @@ def update_history(apps, schema_editor): deltas['quantity'] = float(q) except: print(f"WARNING: Error converting removed quantity '{removed}'") + else: + print(f"Could not decode '{title}'") elif 'split from existing' in title: tracking_type = StockHistoryCode.SPLIT_FROM_PARENT + + deltas['quantity'] = float(q) elif 'moved to' in title: tracking_type = StockHistoryCode.STOCK_MOVE @@ -93,7 +101,7 @@ def update_history(apps, schema_editor): tracking_type = StockHistoryCode.STOCK_ADD # Extract the number of added items - result = re.search("^added ([\d\.]+) items$", title) + result = re.search("^added ([\d\.]+) items", title) if result: @@ -107,6 +115,9 @@ def update_history(apps, schema_editor): except: print(f"WARNING: Error converting added quantity '{added}'") + else: + print(f"Could not decode '{title}'") + elif 'assigned to customer' in title: tracking_type = StockHistoryCode.SENT_TO_CUSTOMER diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 7d55d26f4d..613882ba1a 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -641,8 +641,8 @@ class StockItem(MPTTModel): tracking_info['location_name'] = location.name if self.customer: - tracking_info['customer'] = customer.id - tracking_info['customer_name'] = customer.name + tracking_info['customer'] = self.customer.id + tracking_info['customer_name'] = self.customer.name self.add_tracking_entry( StockHistoryCode.RETURNED_FROM_CUSTOMER, @@ -849,7 +849,7 @@ class StockItem(MPTTModel): StockHistoryCode.REMOVED_CHILD_ITEM, user, deltas={ - 'stockitem': self.pk, + 'stockitem': self.pk, }, notes=notes, url=self.get_absolute_url(), @@ -1183,11 +1183,6 @@ class StockItem(MPTTModel): return True - if self.location: - msg = _("Moved to {loc_new} (from {loc_old})").format(loc_new=str(location), loc_old=str(self.location)) - else: - msg = _('Moved to {loc_new}').format(loc_new=str(location)) - self.location = location tracking_info = {} From 385131137f855b810f7200b917288cfde0a2bace Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 20:55:14 +1000 Subject: [PATCH 145/300] Extract stock location from legacy stocktracking entry - Not 100% accurate - e.g. if the stock location has been altered! --- .../migrations/0061_auto_20210511_0911.py | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py index 2c264aac1d..32cd96d71c 100644 --- a/InvenTree/stock/migrations/0061_auto_20210511_0911.py +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -15,9 +15,26 @@ def update_history(apps, schema_editor): StockItem = apps.get_model('stock', 'stockitem') StockItemTracking = apps.get_model('stock', 'stockitemtracking') + StockLocation = apps.get_model('stock', 'stocklocation') update_count = 0 + locations = StockLocation.objects.all() + + for location in locations: + # Pre-calculate pathstring + # Note we cannot use the 'pathstring' function here as we don't have access to model functions! + + path = [location.name] + + loc = location + + while loc.parent: + loc = loc.parent + path = [loc.name] + path + + location._path = '/'.join(path) + for item in StockItem.objects.all(): history = StockItemTracking.objects.filter(item=item).order_by('date') @@ -27,14 +44,14 @@ def update_history(apps, schema_editor): quantity = history[0].quantity - for entry in history: + for idx, entry in enumerate(history): deltas = {} updated = False q = entry.quantity - if not q == quantity: + if idx == 0 or not q == quantity: try: deltas['quantity']: float(q) @@ -43,7 +60,7 @@ def update_history(apps, schema_editor): print(f"WARNING: Error converting quantity '{q}'") - quantity = q + quantity = q # Try to "guess" the "type" of tracking entry, based on the title title = entry.title.lower() @@ -84,6 +101,46 @@ def update_history(apps, schema_editor): elif 'moved to' in title: tracking_type = StockHistoryCode.STOCK_MOVE + + result = re.search('^Moved to (.*)( - )*(.*) \(from.*$', entry.title) + + if result: + # Legacy tracking entries recorded the location in multiple ways, because.. why not? + text = result.groups()[0] + + matches = set() + + for location in locations: + + # Direct match for pathstring + if text == location._path: + matches.add(location) + + # Direct match for name + if text == location.name: + matches.add(location) + + # Match for "name - description" + compare = f"{location.name} - {location.description}" + + if text == compare: + matches.add(location) + + # Match for "pathstring - description" + compare = f"{location._path} - {location.description}" + + if text == compare: + matches.add(location) + + if len(matches) == 1: + location = list(matches)[0] + + deltas['location'] = location.pk + deltas['location_path'] = location._path + + else: + print(f"No location match: '{text}'") + break elif 'created stock item' in title: tracking_type = StockHistoryCode.CREATED From 0020e85397622aadedad91b56dc2e2b2b4cfbc5f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 20:56:20 +1000 Subject: [PATCH 146/300] Refactor add_tracking_entry --- InvenTree/order/models.py | 10 +++--- InvenTree/stock/models.py | 66 +++++++++++++++++++++------------------ 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 9a521b8044..e5a26386ac 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -370,19 +370,17 @@ class PurchaseOrder(Order): tracking_info = { 'status': status, - 'purchaseorder': self.pk, - 'quantity': quantity, } - if location: - tracking_info['location'] = location.pk - stock.add_tracking_entry( StockHistoryCode.RECEIVED_AGAINST_PURCHASE_ORDER, user, notes=notes, url=self.get_absolute_url(), - deltas=tracking_info + deltas=tracking_info, + location=location, + purchaseorder=self, + quantity=quantity ) # Update the number of parts received against the particular line item diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 613882ba1a..b9188979b7 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -199,17 +199,15 @@ class StockItem(MPTTModel): if add_note: tracking_info = { - 'quantity': self.quantity, 'status': self.status, } - if self.location: - tracking_info['location'] = self.location.pk - self.add_tracking_entry( StockHistoryCode.CREATED, user, - deltas=tracking_info + deltas=tracking_info, + location=self.location, + quantity=self.quantity, ) @property @@ -636,10 +634,6 @@ class StockItem(MPTTModel): tracking_info = {} - if location: - tracking_info['location'] = location.id - tracking_info['location_name'] = location.name - if self.customer: tracking_info['customer'] = self.customer.id tracking_info['customer_name'] = self.customer.name @@ -648,7 +642,8 @@ class StockItem(MPTTModel): StockHistoryCode.RETURNED_FROM_CUSTOMER, user, notes=notes, - deltas=tracking_info + deltas=tracking_info, + location=location ) self.customer = None @@ -856,22 +851,15 @@ class StockItem(MPTTModel): ) tracking_info = { - 'assembly': self.belongs_to.pk + 'stockitem': self.belongs_to.pk } - if location: - tracking_info['location'] = location.pk - tracking_info['location_name'] = location.name - url = location.get_absolute_url() - else: - url = '' - self.add_tracking_entry( StockHistoryCode.REMOVED_FROM_ASSEMBLY, user, notes=notes, - url=url, - deltas=tracking_info + deltas=tracking_info, + location=location, ) # Mark this stock item as *not* belonging to anyone @@ -935,7 +923,7 @@ class StockItem(MPTTModel): def has_tracking_info(self): return self.tracking_info_count > 0 - def add_tracking_entry(self, entry_type, user, deltas={}, notes='', url=''): + def add_tracking_entry(self, entry_type, user, deltas={}, notes='', url='', **kwargs): """ Add a history tracking entry for this StockItem @@ -947,6 +935,25 @@ class StockItem(MPTTModel): url - Optional URL associated with this tracking entry """ + # Has a location been specified? + location = kwargs.get('location', None) + + if location: + deltas['location'] = location.id + deltas['location_path'] = location.pathstring + + # Has a PurchaseOrder been specified? + po = kwargs.get('purchaseorder', None) + + if po: + deltas['purchaseorder'] = po.id + + # Quantity specified? + quantity = kwargs.get('quantity', None) + + if quantity: + deltas['quantity'] = float(quantity) + entry = StockItemTracking.objects.create( item=self, tracking_type=entry_type, @@ -1037,7 +1044,8 @@ class StockItem(MPTTModel): notes=notes, deltas={ 'serial': serial, - } + }, + location=location ) # Remove the equivalent number of items @@ -1126,7 +1134,8 @@ class StockItem(MPTTModel): notes=notes, deltas={ 'stockitem': self.pk, - } + }, + location=location, ) # Remove the specified quantity from THIS stock item @@ -1187,18 +1196,12 @@ class StockItem(MPTTModel): tracking_info = {} - if location: - tracking_info['location'] = location.pk - url = location.get_absolute_url() - else: - url = '' - self.add_tracking_entry( StockHistoryCode.STOCK_MOVE, user, notes=notes, deltas=tracking_info, - url=url, + location=location, ) self.save() @@ -1306,7 +1309,8 @@ class StockItem(MPTTModel): @transaction.atomic def take_stock(self, quantity, user, notes=''): - """ Remove items from stock + """ + Remove items from stock """ # Cannot remove items from a serialized part From a1203aa1e56c4e4406f044b6f491107f83fb6ff1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 21:22:54 +1000 Subject: [PATCH 147/300] Fixes for unit testing --- InvenTree/stock/models.py | 14 +++++++------- InvenTree/stock/tests.py | 11 ++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index b9188979b7..277d5166ee 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -207,7 +207,7 @@ class StockItem(MPTTModel): user, deltas=tracking_info, location=self.location, - quantity=self.quantity, + quantity=float(self.quantity), ) @property @@ -977,7 +977,7 @@ class StockItem(MPTTModel): Args: quantity: Number of items to serialize (integer) - serials: List of serial numbers (list) + serials: List of serial numbers user: User object associated with action notes: Optional notes for tracking location: If specified, serialized items will be placed in the given location @@ -1267,7 +1267,7 @@ class StockItem(MPTTModel): user, notes=notes, deltas={ - 'quantity': self.quantity, + 'quantity': float(self.quantity), } ) @@ -1300,8 +1300,8 @@ class StockItem(MPTTModel): user, notes=notes, deltas={ - 'added': quantity, - 'quantity': self.quantity + 'added': float(quantity), + 'quantity': float(self.quantity), } ) @@ -1332,8 +1332,8 @@ class StockItem(MPTTModel): user, notes=notes, deltas={ - 'removed': quantity, - 'quantity': self.quantity, + 'removed': float(quantity), + 'quantity': float(self.quantity), } ) diff --git a/InvenTree/stock/tests.py b/InvenTree/stock/tests.py index 08fa727547..6bc15b3505 100644 --- a/InvenTree/stock/tests.py +++ b/InvenTree/stock/tests.py @@ -5,6 +5,8 @@ from django.core.exceptions import ValidationError import datetime +from InvenTree.status_codes import StockHistoryCode + from .models import StockLocation, StockItem, StockItemTracking from .models import StockItemTestResult @@ -217,7 +219,7 @@ class StockTest(TestCase): track = StockItemTracking.objects.filter(item=it).latest('id') self.assertEqual(track.item, it) - self.assertIn('Moved to', track.title) + self.assertEqual(track.tracking_type, StockHistoryCode.STOCK_MOVE) self.assertEqual(track.notes, 'Moved to the bathroom') def test_self_move(self): @@ -284,8 +286,7 @@ class StockTest(TestCase): # Check that a tracking item was added track = StockItemTracking.objects.filter(item=it).latest('id') - self.assertIn('Counted', track.title) - self.assertIn('items', track.title) + self.assertEqual(track.tracking_type, StockHistoryCode.STOCK_COUNT) self.assertIn('Counted items', track.notes) n = it.tracking_info.count() @@ -304,7 +305,7 @@ class StockTest(TestCase): # Check that a tracking item was added track = StockItemTracking.objects.filter(item=it).latest('id') - self.assertIn('Added', track.title) + self.assertEqual(track.tracking_type, StockHistoryCode.STOCK_ADD) self.assertIn('Added some items', track.notes) self.assertFalse(it.add_stock(-10, None)) @@ -319,7 +320,7 @@ class StockTest(TestCase): # Check that a tracking item was added track = StockItemTracking.objects.filter(item=it).latest('id') - self.assertIn('Removed', track.title) + self.assertEqual(track.tracking_type, StockHistoryCode.STOCK_REMOVE) self.assertIn('Removed some items', track.notes) self.assertTrue(it.has_tracking_info) From 93e6eb6dc74b68708c753f71936e2913ff49d359 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 22:26:03 +1000 Subject: [PATCH 148/300] Unit test fixes --- InvenTree/order/models.py | 2 +- .../migrations/0061_auto_20210511_0911.py | 1 - .../migrations/0062_auto_20210511_2151.py | 23 +++++++++++++++++++ InvenTree/stock/models.py | 19 ++++----------- 4 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 InvenTree/stock/migrations/0062_auto_20210511_2151.py diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index e5a26386ac..ddb1f5ceea 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -370,13 +370,13 @@ class PurchaseOrder(Order): tracking_info = { 'status': status, + 'purchaseorder': self.pk, } stock.add_tracking_entry( StockHistoryCode.RECEIVED_AGAINST_PURCHASE_ORDER, user, notes=notes, - url=self.get_absolute_url(), deltas=tracking_info, location=location, purchaseorder=self, diff --git a/InvenTree/stock/migrations/0061_auto_20210511_0911.py b/InvenTree/stock/migrations/0061_auto_20210511_0911.py index 32cd96d71c..0ab37250c8 100644 --- a/InvenTree/stock/migrations/0061_auto_20210511_0911.py +++ b/InvenTree/stock/migrations/0061_auto_20210511_0911.py @@ -136,7 +136,6 @@ def update_history(apps, schema_editor): location = list(matches)[0] deltas['location'] = location.pk - deltas['location_path'] = location._path else: print(f"No location match: '{text}'") diff --git a/InvenTree/stock/migrations/0062_auto_20210511_2151.py b/InvenTree/stock/migrations/0062_auto_20210511_2151.py new file mode 100644 index 0000000000..18832819ff --- /dev/null +++ b/InvenTree/stock/migrations/0062_auto_20210511_2151.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2 on 2021-05-11 11:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0061_auto_20210511_0911'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitemtracking', + name='notes', + field=models.CharField(blank=True, help_text='Entry notes', max_length=512, null=True, verbose_name='Notes'), + ), + migrations.AlterField( + model_name='stockitemtracking', + name='title', + field=models.CharField(blank=True, help_text='Tracking entry title', max_length=250, null=True, verbose_name='Title'), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 277d5166ee..ac870fad75 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -805,9 +805,8 @@ class StockItem(MPTTModel): StockHistoryCode.INSTALLED_INTO_ASSEMBLY, user, notes=notes, - url=self.get_absolute_url(), deltas={ - 'assembly': self.pk, + 'stockitem': self.pk, } ) @@ -816,7 +815,6 @@ class StockItem(MPTTModel): StockHistoryCode.INSTALLED_CHILD_ITEM, user, notes=notes, - url=stock_item.get_absolute_url(), deltas={ 'stockitem': stock_item.pk, } @@ -847,7 +845,6 @@ class StockItem(MPTTModel): 'stockitem': self.pk, }, notes=notes, - url=self.get_absolute_url(), ) tracking_info = { @@ -923,7 +920,7 @@ class StockItem(MPTTModel): def has_tracking_info(self): return self.tracking_info_count > 0 - def add_tracking_entry(self, entry_type, user, deltas={}, notes='', url='', **kwargs): + def add_tracking_entry(self, entry_type, user, deltas={}, notes='', **kwargs): """ Add a history tracking entry for this StockItem @@ -940,13 +937,6 @@ class StockItem(MPTTModel): if location: deltas['location'] = location.id - deltas['location_path'] = location.pathstring - - # Has a PurchaseOrder been specified? - po = kwargs.get('purchaseorder', None) - - if po: - deltas['purchaseorder'] = po.id # Quantity specified? quantity = kwargs.get('quantity', None) @@ -961,7 +951,6 @@ class StockItem(MPTTModel): date=datetime.now(), notes=notes, deltas=deltas, - link=url, system=True ) @@ -1639,14 +1628,14 @@ class StockItemTracking(models.Model): date = models.DateTimeField(auto_now_add=True, editable=False) title = models.CharField( - blank=True, + blank=True, null=True, max_length=250, verbose_name=_('Title'), help_text=_('Tracking entry title') ) notes = models.CharField( - blank=True, + blank=True, null=True, max_length=512, verbose_name=_('Notes'), help_text=_('Entry notes') From 0c19a94f5c060a82a4f3dde495ed2197d8c7cb51 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 22:50:58 +1000 Subject: [PATCH 149/300] Add run-time addition of extra data to the API --- InvenTree/stock/api.py | 58 ++++++++++- InvenTree/templates/js/stock.js | 175 ++++++++++++++++++++++++-------- 2 files changed, 192 insertions(+), 41 deletions(-) diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index c7914827e7..3443c9982f 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -22,7 +22,10 @@ from part.models import Part, PartCategory from part.serializers import PartBriefSerializer from company.models import SupplierPart -from company.serializers import SupplierPartSerializer +from company.serializers import CompanySerializer, SupplierPartSerializer + +from order.models import PurchaseOrder +from order.serializers import POSerializer import common.settings import common.models @@ -992,6 +995,59 @@ class StockTrackingList(generics.ListAPIView): return self.serializer_class(*args, **kwargs) + def list(self, request, *args, **kwargs): + + queryset = self.filter_queryset(self.get_queryset()) + + serializer = self.get_serializer(queryset, many=True) + + data = serializer.data + + # Attempt to add extra context information to the historical data + for item in data: + deltas = item['deltas'] + + # Add location detail + if 'location' in deltas: + try: + location = StockLocation.objects.get(pk=deltas['location']) + serializer = LocationSerializer(location) + deltas['location_detail'] = serializer.data + except: + pass + + # Add stockitem detail + if 'stockitem' in deltas: + try: + stockitem = StockItem.objects.get(pk=deltas['stockitem']) + serializer = StockItemSerializer(stockitem) + deltas['stockitem_detail'] = serializer.data + except: + pass + + # Add customer detail + if 'customer' in deltas: + try: + customer = Company.objects.get(pk=deltas['customer']) + serializer = CompanySerializer(location) + deltas['customer_detail'] = serializer.data + except: + pass + + # Add purchaseorder detail + if 'purchaseorder' in deltas: + try: + order = PurchaseOrder.objects.get(pk=deltas['purchaseorder']) + serializer = POSerializer(order) + deltas['purchaseorder_detail'] = serializer.data + except: + pass + + if request.is_ajax(): + return JsonResponse(data, safe=False) + else: + return Response(data) + def create(self, request, *args, **kwargs): """ Create a new StockItemTracking object diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 4e5d78d8cd..f3f1c7a6bd 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -976,42 +976,28 @@ function loadStockLocationTable(table, options) { function loadStockTrackingTable(table, options) { - var cols = [ - { - field: 'pk', - visible: false, - }, - { - field: 'date', - title: '{% trans "Date" %}', - sortable: true, - formatter: function(value, row, index, field) { - var m = moment(value); - if (m.isValid()) { - var html = m.format('dddd MMMM Do YYYY'); // + '
    ' + m.format('h:mm a'); - return html; - } + var cols = []; - return 'N/A'; - } - }, - ]; + // Date + cols.push({ + field: 'date', + title: '{% trans "Date" %}', + sortable: true, + formatter: function(value, row, index, field) { + var m = moment(value); - // If enabled, provide a link to the referenced StockItem - if (options.partColumn) { - cols.push({ - field: 'item', - title: '{% trans "Stock Item" %}', - sortable: true, - formatter: function(value, row, index, field) { - return renderLink(value.part_name, value.url); + if (m.isValid()) { + var html = m.format('dddd MMMM Do YYYY'); // + '
    ' + m.format('h:mm a'); + return html; } - }); - } + + return '{% trans "Invalid date" %}'; + } + }); // Stock transaction description cols.push({ - field: 'title', + field: 'label', title: '{% trans "Description" %}', formatter: function(value, row, index, field) { var html = "" + value + ""; @@ -1020,20 +1006,129 @@ function loadStockTrackingTable(table, options) { html += "
    " + row.notes + ""; } - if (row.link) { - html += "
    " + row.link + ""; - } - return html; } }); + // Stock transaction details cols.push({ - field: 'quantity', - title: '{% trans "Quantity" %}', - formatter: function(value, row, index, field) { - return parseFloat(value); - }, + field: 'deltas', + title: '{% trans "Details" %}', + formatter: function(details, row, index, field) { + var html = `
    {% trans 'Part' %}
    {% trans "Part name" %}{{ part.name }}{{ part.name }}{% include "clip.html"%}
    {% trans "IPN" %}{{ part.IPN }}{{ part.IPN }}{% include "clip.html"%}
    {% trans "Revision" %}{{ part.revision }}{{ part.revision }}{% include "clip.html"%}
    {% trans "Latest Serial Number" %} {% if part.getLatestSerialNumber %} - {{ part.getLatestSerialNumber }} + {{ part.getLatestSerialNumber }}{% include "clip.html"%} {% else %} {% trans "No serial numbers recorded" %} {% endif %} @@ -52,7 +52,7 @@
    {% trans "Description" %}{{ part.description }}{{ part.description }}{% include "clip.html"%}
    {% trans "Default Supplier" %} - {{ part.default_supplier.supplier.name }} | {{ part.default_supplier.SKU }} + {{ part.default_supplier.supplier.name }} | {{ part.default_supplier.SKU }}{% include "clip.html"%}
    - {{ row.index }} + {% add row.index 1 %} {% for field in form.visible_fields %} @@ -71,6 +71,12 @@ {% if row.errors.quantity %}

    {{ row.errors.quantity }}

    {% endif %} + {% elif item.column.guess == 'Purchase_Price' %} + {% for field in form.visible_fields %} + {% if field.name == row.price_select %} + {{ field }} + {% endif %} + {% endfor %} {% else %} {{ item.cell }} {% endif %} diff --git a/InvenTree/order/templates/order/order_wizard/po_upload.html b/InvenTree/order/templates/order/order_wizard/po_upload.html index 84a28cf0a3..a281725173 100644 --- a/InvenTree/order/templates/order/order_wizard/po_upload.html +++ b/InvenTree/order/templates/order/order_wizard/po_upload.html @@ -13,6 +13,7 @@ {% endblock %} {% block details %} +{% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}

    {% blocktrans with step=wizard.steps.step1 count=wizard.steps.count %}Step {{step}} of {{count}}{% endblocktrans %} {% if description %}- {{ description }}{% endif %}

    @@ -42,6 +43,11 @@ {% endblock form_buttons_bottom %} +{% else %} + +{% endif %} {% endblock details %} {% block js_ready %} diff --git a/InvenTree/order/templates/order/po_navbar.html b/InvenTree/order/templates/order/po_navbar.html index d49af69c84..f8e818c2e3 100644 --- a/InvenTree/order/templates/order/po_navbar.html +++ b/InvenTree/order/templates/order/po_navbar.html @@ -1,6 +1,7 @@ {% load i18n %} {% load static %} {% load inventree_extras %} +{% load status_codes %}
    {% trans "File Fields" %}
    @@ -49,8 +49,8 @@
    {% trans "Match Fields" %} {{ col }} @@ -65,18 +65,18 @@ {% endfor %}
    - + {{ row_index }}{{ row_index }} - {{ item.cell }} + {{ item }}
    {% trans "Row" %} {% trans "Select Supplier Part" %}{% trans "Quantity" %} @@ -35,6 +38,7 @@ {{ col.name }} {% endif %}
    - - {% add row.index 1 %} + {{ row.index }} {% for field in form.visible_fields %} @@ -60,18 +63,20 @@

    {{ row.errors.part }}

    {% endif %}
    - {% if item.column.guess == 'Quantity' %} - {% for field in form.visible_fields %} - {% if field.name == row.quantity_select %} - {{ field }} - {% endif %} - {% endfor %} - {% if row.errors.quantity %} -

    {{ row.errors.quantity }}

    + {% for field in form.visible_fields %} + {% if field.name == row.quantity_select %} + {{ field }} {% endif %} - {% elif item.column.guess == 'Purchase_Price' %} + {% endfor %} + {% if row.errors.quantity %} +

    {{ row.errors.quantity }}

    + {% endif %} +
    + {% if item.column.guess == 'Purchase_Price' %} {% for field in form.visible_fields %} {% if field.name == row.price_select %} {{ field }} @@ -82,6 +87,7 @@ {% endif %}
    `; + + // Location information + if (details.location) { + + html += ``; + + html += ''; + } + + // Purchase Order Information + if (details.purchaseorder) { + + html += `'; + } + + // Customer information + if (details.customer) { + + html += `'; + } + + // Stockitem information + if (details.stockitem) { + html += ''; + } + + // Status information + if (details.status) { + + } + + // Quantity information + if (details.added) { + html += ''; + + html += ``; + + html += ''; + } + + if (details.removed) { + html += ''; + + html += ``; + + html += ''; + } + + if (details.quantity) { + html += ''; + + html += ``; + + html += ''; + } + + html += '
    {% trans "Location" %}'; + + if (details.location_detail) { + // A valid location is provided + + html += renderLink( + details.location_detail.pathstring, + details.location_detail.url, + ); + } else { + // An invalid location (may have been deleted?) + html += `{% trans "Location no longer exists" %}`; + } + + html += '
    {% trans "Purchase Order" %}`; + + html += ''; + + if (details.purchaseorder_detail) { + html += renderLink( + details.purchaseorder_detail.reference, + `/order/purchase-order/${details.purchaseorder}/` + ); + } else { + html += `{% trans "Purchase order no longer exists" %}`; + } + + html += '
    {% trans "Customer" %}`; + + html += ''; + + if (details.customer_detail) { + html += renderLink( + details.customer_detail.name, + details.customer_detail.url + ); + } else { + html += `{% trans "Customer no longer exists" %}`; + } + + html += '
    {% trans "Stock Item" %}'; + + html += ''; + + if (details.stockitem_detail) { + html += renderLink( + details.stockitem, + `/stock/item/${details.stockitem}/` + ); + } else { + html += `{% trans "Stock item no longer exists" %}`; + } + + html += '
    {% trans "Added" %}${details.added}
    {% trans "Removed" %}${details.removed}
    {% trans "Quantity" %}${details.quantity}
    '; + + return html; + } }); cols.push({ @@ -1056,7 +1151,7 @@ function loadStockTrackingTable(table, options) { sortable: false, formatter: function(value, row, index, field) { // Manually created entries can be edited or deleted - if (!row.system) { + if (false && !row.system) { var bEdit = ""; var bDel = ""; From 84bfffd5a716531956607006805031b617d62964 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 22:51:29 +1000 Subject: [PATCH 150/300] Override 'add_note' when new StockItem is created - This allows us to prevent the issue of duplicate notes being created --- InvenTree/order/models.py | 2 +- InvenTree/stock/models.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index ddb1f5ceea..5305038b4f 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -366,7 +366,7 @@ class PurchaseOrder(Order): purchase_price=purchase_price, ) - stock.save() + stock.save(add_note=False) tracking_info = { 'status': status, diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index ac870fad75..4076b27c97 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -183,9 +183,12 @@ class StockItem(MPTTModel): self.validate_unique() self.clean() + # If 'add_note = False' specified, then no tracking note will be added for item creation + add_note = kwargs.pop('add_note', True) + if not self.pk: # StockItem has not yet been saved - add_note = True + add_note = add_note and True else: # StockItem has already been saved add_note = False From 03a231bffb2e5391bba1f3c34db145f3c8233764 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 11 May 2021 23:38:26 +1000 Subject: [PATCH 151/300] Updates - Add StockHistoryCode to custom context - Add simple form for editing stock item history - Add tracking entry when stock status is changed --- InvenTree/InvenTree/context.py | 2 ++ InvenTree/InvenTree/status_codes.py | 2 ++ InvenTree/stock/api.py | 28 ++++++++++----- InvenTree/stock/forms.py | 12 +++++++ InvenTree/stock/models.py | 35 ++++++++++++++++--- .../stock/templates/stock/item_base.html | 19 ++++++++++ InvenTree/stock/urls.py | 3 +- InvenTree/stock/views.py | 10 ++++++ InvenTree/templates/js/stock.js | 13 +++++++ InvenTree/templates/js/table_filters.js | 1 + InvenTree/templates/status_codes.html | 10 ++++-- 11 files changed, 119 insertions(+), 16 deletions(-) diff --git a/InvenTree/InvenTree/context.py b/InvenTree/InvenTree/context.py index 669b55b0c0..3e1f98ffc2 100644 --- a/InvenTree/InvenTree/context.py +++ b/InvenTree/InvenTree/context.py @@ -6,6 +6,7 @@ Provides extra global data to all templates. from InvenTree.status_codes import SalesOrderStatus, PurchaseOrderStatus from InvenTree.status_codes import BuildStatus, StockStatus +from InvenTree.status_codes import StockHistoryCode import InvenTree.status @@ -65,6 +66,7 @@ def status_codes(request): 'PurchaseOrderStatus': PurchaseOrderStatus, 'BuildStatus': BuildStatus, 'StockStatus': StockStatus, + 'StockHistoryCode': StockHistoryCode, } diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index 53b747a9ad..63fc8a491c 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -7,6 +7,8 @@ class StatusCode: This is used to map a set of integer values to text. """ + colors = {} + @classmethod def render(cls, key, large=False): """ diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 3443c9982f..b0b6ae1c24 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -21,7 +21,7 @@ from .models import StockItemTestResult from part.models import Part, PartCategory from part.serializers import PartBriefSerializer -from company.models import SupplierPart +from company.models import Company, SupplierPart from company.serializers import CompanySerializer, SupplierPartSerializer from order.models import PurchaseOrder @@ -100,6 +100,16 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView): return self.serializer_class(*args, **kwargs) + def update(self, request, *args, **kwargs): + """ + Record the user who updated the item + """ + + # TODO: Record the user! + # user = request.user + + return super().update(request, *args, **kwargs) + class StockFilter(FilterSet): """ FilterSet for advanced stock filtering. @@ -374,25 +384,25 @@ class StockList(generics.ListCreateAPIView): we can pre-fill the location automatically. """ + user = request.user + serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - item = serializer.save() + item = serializer.save(user=user, commit=False) # A location was *not* specified - try to infer it if 'location' not in request.data: - location = item.part.get_default_location() - - if location is not None: - item.location = location - item.save() + item.location = item.part.get_default_location() # An expiry date was *not* specified - try to infer it! if 'expiry_date' not in request.data: if item.part.default_expiry > 0: item.expiry_date = datetime.now().date() + timedelta(days=item.part.default_expiry) - item.save() + + # Finally, save the item + item.save(user=user) # Return a response headers = self.get_success_headers(serializer.data) @@ -1029,7 +1039,7 @@ class StockTrackingList(generics.ListAPIView): if 'customer' in deltas: try: customer = Company.objects.get(pk=deltas['customer']) - serializer = CompanySerializer(location) + serializer = CompanySerializer(customer) deltas['customer_detail'] = serializer.data except: pass diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py index 3fb72ebe1e..6d7f8d40ed 100644 --- a/InvenTree/stock/forms.py +++ b/InvenTree/stock/forms.py @@ -393,6 +393,18 @@ class AdjustStockForm(forms.ModelForm): ] +class EditStockItemStatusForm(HelperForm): + """ + Simple form for editing StockItem status field + """ + + class Meta: + model = StockItem + fields = [ + 'status', + ] + + class EditStockItemForm(HelperForm): """ Form for editing a StockItem object. Note that not all fields can be edited here (even if they can be specified during creation. diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 4076b27c97..bae1bc5135 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -183,20 +183,46 @@ class StockItem(MPTTModel): self.validate_unique() self.clean() + user = kwargs.pop('user', None) + # If 'add_note = False' specified, then no tracking note will be added for item creation add_note = kwargs.pop('add_note', True) + notes = kwargs.pop('notes', '') + if not self.pk: # StockItem has not yet been saved add_note = add_note and True else: # StockItem has already been saved + + # Check if "interesting" fields have been changed + # (we wish to record these as historical records) + + try: + old = StockItem.objects.get(pk=self.pk) + + deltas = {} + + # Status changed? + if not old.status == self.status: + deltas['status'] = self.status + + # TODO - Other interesting changes we are interested in... + + if add_note and len(deltas) > 0: + self.add_tracking_entry( + StockHistoryCode.EDITED, + user, + deltas=deltas, + notes=notes, + ) + + except (ValueError, StockItem.DoesNotExist): + pass + add_note = False - user = kwargs.pop('user', None) - - add_note = add_note and kwargs.pop('note', True) - super(StockItem, self).save(*args, **kwargs) if add_note: @@ -209,6 +235,7 @@ class StockItem(MPTTModel): StockHistoryCode.CREATED, user, deltas=tracking_info, + notes=notes, location=self.location, quantity=float(self.quantity), ) diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index c7e0dc15dd..54d6b12e4f 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -94,7 +94,13 @@ {% if item.is_expired %} {% trans "Expired" %} {% else %} + {% if roles.stock.change %} + + {% endif %} {% stock_status_label item.status large=True %} + {% if roles.stock.change %} + + {% endif %} {% if item.is_stale %} {% trans "Stale" %} {% endif %} @@ -453,6 +459,7 @@ $("#print-label").click(function() { printStockItemLabels([{{ item.pk }}]); }); +{% if roles.stock.change %} $("#stock-duplicate").click(function() { createNewStockItem({ follow: true, @@ -472,6 +479,18 @@ $("#stock-edit").click(function () { ); }); +$('#stock-edit-status').click(function () { + launchModalForm( + "{% url 'stock-item-edit-status' item.id %}", + { + reload: true, + submit_text: '{% trans "Save" %}', + } + ); +}); + +{% endif %} + $("#show-qr-code").click(function() { launchModalForm("{% url 'stock-item-qr' item.id %}", { diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index fe5472003f..dbdbdda317 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -4,7 +4,7 @@ URL lookup for Stock app from django.conf.urls import url, include -from . import views +from stock import views location_urls = [ @@ -24,6 +24,7 @@ location_urls = [ ] stock_item_detail_urls = [ + url(r'^edit_status/', views.StockItemEditStatus.as_view(), name='stock-item-edit-status'), url(r'^edit/', views.StockItemEdit.as_view(), name='stock-item-edit'), url(r'^convert/', views.StockItemConvert.as_view(), name='stock-item-convert'), url(r'^serialize/', views.StockItemSerialize.as_view(), name='stock-item-serialize'), diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 0984405055..38757d4cf2 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -1212,6 +1212,16 @@ class StockAdjust(AjaxView, FormMixin): return _("Deleted {n} stock items").format(n=count) +class StockItemEditStatus(AjaxUpdateView): + """ + View for editing stock item status field + """ + + model = StockItem + form_class = StockForms.EditStockItemStatusForm + ajax_form_title = _('Edit Stock Item Status') + + class StockItemEdit(AjaxUpdateView): """ View for editing details of a single StockItem diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index f3f1c7a6bd..a0601aeb13 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -1097,6 +1097,16 @@ function loadStockTrackingTable(table, options) { // Status information if (details.status) { + html += `{% trans "Status" %}`; + + html += ''; + html += stockStatusDisplay( + details.status, + { + classes: 'float-right', + } + ); + html += ''; } @@ -1147,6 +1157,8 @@ function loadStockTrackingTable(table, options) { } }); + /* + // 2021-05-11 - Ability to edit or delete StockItemTracking entries is now removed cols.push({ sortable: false, formatter: function(value, row, index, field) { @@ -1161,6 +1173,7 @@ function loadStockTrackingTable(table, options) { } } }); + */ table.inventreeTable({ method: 'get', diff --git a/InvenTree/templates/js/table_filters.js b/InvenTree/templates/js/table_filters.js index 775f0d9803..5f516e9419 100644 --- a/InvenTree/templates/js/table_filters.js +++ b/InvenTree/templates/js/table_filters.js @@ -3,6 +3,7 @@ {% load inventree_extras %} {% include "status_codes.html" with label='stock' options=StockStatus.list %} +{% include "status_codes.html" with label='stockHistory' options=StockHistoryCode.list %} {% include "status_codes.html" with label='build' options=BuildStatus.list %} {% include "status_codes.html" with label='purchaseOrder' options=PurchaseOrderStatus.list %} {% include "status_codes.html" with label='salesOrder' options=SalesOrderStatus.list %} diff --git a/InvenTree/templates/status_codes.html b/InvenTree/templates/status_codes.html index f032f97309..e7bc2e951c 100644 --- a/InvenTree/templates/status_codes.html +++ b/InvenTree/templates/status_codes.html @@ -14,7 +14,7 @@ var {{ label }}Codes = { * Uses the values specified in "status_codes.py" * This function is generated by the "status_codes.html" template */ -function {{ label }}StatusDisplay(key) { +function {{ label }}StatusDisplay(key, options={}) { key = String(key); @@ -31,5 +31,11 @@ function {{ label }}StatusDisplay(key) { label = ''; } - return `${value}`; + var classes = `label ${label}`; + + if (options.classes) { + classes += ' ' + options.classes; + } + + return `${value}`; } From 71c3ff4b9fdeb6c7580defec8fdc3ca1f9b303c2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 11 May 2021 16:15:10 +0200 Subject: [PATCH 152/300] prefetching related information --- InvenTree/part/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 6f8d66de21..1fdc5b60e3 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -2043,7 +2043,8 @@ class PartPricing(AjaxView): # Stock history if part_settings.part_show_graph and part.total_stock > 1: ret = [] - stock = part.stock_entries(include_variants=False, in_stock=True) + stock = part.stock_entries(include_variants=False, in_stock=True) #.order_by('purchase_order__date') + stock = stock.prefetch_related('purchase_order', 'supplier_part') for stock_item in stock: if None in [stock_item.purchase_price, stock_item.quantity]: From 169745c11f022120d35b6704bb2403bccca9dd2f Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 11 May 2021 16:23:26 +0200 Subject: [PATCH 153/300] style fix --- InvenTree/part/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 1fdc5b60e3..a2986fe869 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -2043,7 +2043,7 @@ class PartPricing(AjaxView): # Stock history if part_settings.part_show_graph and part.total_stock > 1: ret = [] - stock = part.stock_entries(include_variants=False, in_stock=True) #.order_by('purchase_order__date') + stock = part.stock_entries(include_variants=False, in_stock=True) # .order_by('purchase_order__date') stock = stock.prefetch_related('purchase_order', 'supplier_part') for stock_item in stock: From a093118856b30a6d7ea0dd63a7eabbb4b73a8e8e Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 11 May 2021 11:02:54 -0400 Subject: [PATCH 154/300] Few more fixes --- InvenTree/common/forms.py | 21 ++++++++++++++-- InvenTree/common/views.py | 25 ++++--------------- .../order/order_wizard/match_fields.html | 2 +- .../order/order_wizard/match_parts.html | 9 ++++--- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index d00b868e04..5e698558b8 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -5,6 +5,8 @@ Django forms for interacting with common objects # -*- coding: utf-8 -*- from __future__ import unicode_literals +from decimal import Decimal, InvalidOperation + from django import forms from django.utils.translation import gettext as _ @@ -117,6 +119,21 @@ class MatchItem(forms.Form): super().__init__(*args, **kwargs) + def clean(number): + """ Clean-up decimal value """ + + # Check if empty + if not number: + return number + + # Check if decimal type + try: + clean_number = Decimal(number) + except InvalidOperation: + clean_number = number + + return clean_number.quantize(Decimal(1)) if clean_number == clean_number.to_integral() else clean_number.normalize() + # Setup FileManager file_manager.setup() @@ -143,7 +160,7 @@ class MatchItem(forms.Form): 'type': 'number', 'min': '0', 'step': 'any', - 'value': row['quantity'], + 'value': clean(row['quantity']), }) ) # else: @@ -187,7 +204,7 @@ class MatchItem(forms.Form): decimal_places=5, max_digits=19, required=False, - default_amount=value, + default_amount=clean(value), ) # else: # self.fields[field_name] = forms.TextInput() diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index d13edcfe28..904f09062e 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -205,10 +205,9 @@ class FileManagementFormView(MultiStepFormView): stored_data = self.storage.get_step_data(self.steps.current) if stored_data: self.get_form_table_data(stored_data) - else: - if form.is_valid() or self.steps.current == 'items': - # Set form table data - self.set_form_table_data(form=form) + elif self.steps.current == 'items': + # Set form table data + self.set_form_table_data(form=form) # Update context context.update({'rows': self.rows}) @@ -357,15 +356,11 @@ class FileManagementFormView(MultiStepFormView): # Re-construct the row data self.rows = [] - # if self.column_names: - # rows_shown = [] - # Update the row data - for row_idx in sorted(self.row_data.keys()): - row_data = self.row_data[row_idx] + for row_idx, row_key in enumerate(sorted(self.row_data.keys())): + row_data = self.row_data[row_key] data = [] - # show_data = [] for idx, item in row_data.items(): column_data = { @@ -379,8 +374,6 @@ class FileManagementFormView(MultiStepFormView): 'column': column_data, } data.append(cell_data) - # if not self.column_names or column_data.get('name', '') in self.column_names: - # show_data.append(cell_data) row = { 'index': row_idx, @@ -388,14 +381,6 @@ class FileManagementFormView(MultiStepFormView): 'errors': {}, } self.rows.append(row) - - # if self.column_names: - # current_row = row - # current_row['data'] = show_data - # rows_shown.append(current_row) - - # if self.column_names and self.get_step_index() == 3: - # self.rows = rows_shown # In the item selection step: update row data to contain fields if form and self.steps.current == 'items': diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index 652226377b..4ff7b6a963 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -65,7 +65,7 @@ {% endfor %} {% for row in rows %} - {% with forloop.counter0 as row_index %} + {% with forloop.counter as row_index %} - {{ row.index }} + {% add row.index 1 %} {% for field in form.visible_fields %} From ba561d6d194d4fab0c9aacc876b217b330b604d5 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 11 May 2021 14:06:38 -0400 Subject: [PATCH 155/300] Fixed import for excel formats --- InvenTree/common/files.py | 13 +++++++------ requirements.txt | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/InvenTree/common/files.py b/InvenTree/common/files.py index 976daf992d..377120f44d 100644 --- a/InvenTree/common/files.py +++ b/InvenTree/common/files.py @@ -49,28 +49,27 @@ class FileManager: cleaned_data = None - ext = os.path.splitext(file.name)[-1].lower() + ext = os.path.splitext(file.name)[-1].lower().replace('.', '') - if ext in ['.csv', '.tsv', ]: + if ext in ['csv', 'tsv', ]: # These file formats need string decoding raw_data = file.read().decode('utf-8') # Reset stream position to beginning of file file.seek(0) - elif ext in ['.xls', '.xlsx', '.json', '.yaml', ]: + elif ext in ['xls', 'xlsx', 'json', 'yaml', ]: raw_data = file.read() # Reset stream position to beginning of file file.seek(0) else: - raise ValidationError(_(f'Unsupported file format: {ext}')) + raise ValidationError(_(f'Unsupported file format: {ext.upper()}')) try: - cleaned_data = tablib.Dataset().load(raw_data) + cleaned_data = tablib.Dataset().load(raw_data, format=ext) except tablib.UnsupportedFormat: raise ValidationError(_('Error reading file (invalid format)')) except tablib.core.InvalidDimensions: raise ValidationError(_('Error reading file (incorrect dimension)')) except KeyError: - # TODO: Find fix for XLSX format as it keeps on returning a KeyError raise ValidationError(_('Error reading file (data could be corrupted)')) return cleaned_data @@ -209,6 +208,8 @@ class FileManager: data[idx] = int(item) except ValueError: pass + except TypeError: + data[idx] = '' # Skip empty rows if empty: diff --git a/requirements.txt b/requirements.txt index beaa30c4fe..0f5f518217 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,9 +11,10 @@ django-markdownx==3.0.1 # Markdown form fields django-markdownify==0.8.0 # Markdown rendering coreapi==2.3.0 # API documentation pygments==2.7.4 # Syntax highlighting -tablib==0.13.0 # Import / export data files +# tablib==0.13.0 # Import / export data files (installed as dependency of django-import-export package) django-crispy-forms==1.11.2 # Form helpers django-import-export==2.0.0 # Data import / export for admin interface +tablib[xls,xlsx] # Support for XLS and XLSX formats django-cleanup==5.1.0 # Manage deletion of old / unused uploaded files flake8==3.8.3 # PEP checking pep8-naming==0.11.1 # PEP naming convention extension From 7e6ac54015b5e73d9df83ea577ef410dd15180ab Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 11 May 2021 14:13:21 -0400 Subject: [PATCH 156/300] YAML does not get installed during django-import-export package? --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0f5f518217..35963ce718 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ pygments==2.7.4 # Syntax highlighting # tablib==0.13.0 # Import / export data files (installed as dependency of django-import-export package) django-crispy-forms==1.11.2 # Form helpers django-import-export==2.0.0 # Data import / export for admin interface -tablib[xls,xlsx] # Support for XLS and XLSX formats +tablib[xls,xlsx,yaml] # Support for XLS and XLSX formats django-cleanup==5.1.0 # Manage deletion of old / unused uploaded files flake8==3.8.3 # PEP checking pep8-naming==0.11.1 # PEP naming convention extension From e9c4ce8c5f3fadd7748a02d26cce620e895adc8f Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 11 May 2021 17:11:09 -0400 Subject: [PATCH 157/300] Added support for reference and notes fields --- InvenTree/common/forms.py | 11 ++- InvenTree/common/views.py | 25 +++-- .../order/order_wizard/match_parts.html | 16 +++- InvenTree/order/views.py | 91 ++++++++----------- 4 files changed, 72 insertions(+), 71 deletions(-) diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index 5e698558b8..8a0017e38b 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -160,11 +160,9 @@ class MatchItem(forms.Form): 'type': 'number', 'min': '0', 'step': 'any', - 'value': clean(row['quantity']), + 'value': clean(row.get('quantity', '')), }) ) - # else: - # self.fields[field_name] = forms.TextInput() # Create item selection box elif col_guess in file_manager.ITEM_MATCH_HEADERS: @@ -206,5 +204,8 @@ class MatchItem(forms.Form): required=False, default_amount=clean(value), ) - # else: - # self.fields[field_name] = forms.TextInput() + else: + self.fields[field_name] = forms.CharField( + required=False, + initial=value, + ) diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 904f09062e..fa605c2b80 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -188,11 +188,6 @@ class FileManagementFormView(MultiStepFormView): media_folder = 'file_upload/' extra_context_data = {} - # Set keys for item matching - key_item_select = 'item_select' - key_quantity_select = 'quantity' - key_price_select = 'price' - def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) @@ -382,16 +377,20 @@ class FileManagementFormView(MultiStepFormView): } self.rows.append(row) - # In the item selection step: update row data to contain fields + # In the item selection step: update row data with mapping to form fields if form and self.steps.current == 'items': - # Update row data + # Find field keys + field_keys = [] + for field in form.fields: + field_key = field.split('-')[0] + if field_key not in field_keys: + field_keys.append(field_key) + + # Populate rows for row in self.rows: - # Add item select field - row['item_select'] = self.key_item_select + '-' + str(row['index']) - # Add quantity select field - row['quantity_select'] = self.key_quantity_select + '-' + str(row['index']) - # Add price select field - row['price_select'] = self.key_price_select + '-' + str(row['index']) + for field_key in field_keys: + # Map row data to field + row[field_key] = field_key + '-' + str(row['index']) def get_column_index(self, name): """ Return the index of the column with the given name. diff --git a/InvenTree/order/templates/order/order_wizard/match_parts.html b/InvenTree/order/templates/order/order_wizard/match_parts.html index 0ad5c2483c..f97edff913 100644 --- a/InvenTree/order/templates/order/order_wizard/match_parts.html +++ b/InvenTree/order/templates/order/order_wizard/match_parts.html @@ -66,7 +66,7 @@ {% for field in form.visible_fields %} - {% if field.name == row.quantity_select %} + {% if field.name == row.quantity %} {{ field }} {% endif %} {% endfor %} @@ -79,7 +79,19 @@ {% if item.column.guess == 'Purchase_Price' %} {% for field in form.visible_fields %} - {% if field.name == row.price_select %} + {% if field.name == row.purchase_price %} + {{ field }} + {% endif %} + {% endfor %} + {% elif item.column.guess == 'Reference' %} + {% for field in form.visible_fields %} + {% if field.name == row.reference %} + {{ field }} + {% endif %} + {% endfor %} + {% elif item.column.guess == 'Notes' %} + {% for field in form.visible_fields %} + {% if field.name == row.notes %} {{ field }} {% endif %} {% endfor %} diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index c30231abd1..cf79746f0d 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -583,7 +583,14 @@ class PurchaseOrderUpload(FileManagementFormView): _("Match Fields"), _("Match Supplier Parts"), ] - key_price_select = 'purchase_price' + # Form field name: PurchaseOrderLineItem field + form_field_map = { + 'item_select': 'part', + 'quantity': 'quantity', + 'purchase_price': 'purchase_price', + 'reference': 'reference', + 'notes': 'notes', + } def get_order(self): """ Get order or return 404 """ @@ -680,7 +687,7 @@ class PurchaseOrderUpload(FileManagementFormView): p_val = p_val.replace(',', '') try: - # Attempt to extract a valid quantity from the field + # Attempt to extract a valid decimal value from the field purchase_price = Decimal(p_val) # Store the 'purchase_price' value row['purchase_price'] = purchase_price @@ -689,11 +696,13 @@ class PurchaseOrderUpload(FileManagementFormView): # Check if there is a column corresponding to "reference" if r_idx >= 0: - pass + reference = row['data'][r_idx]['cell'] + row['reference'] = reference # Check if there is a column corresponding to "notes" if n_idx >= 0: - pass + notes = row['data'][n_idx]['cell'] + row['notes'] = notes def done(self, form_list, **kwargs): """ Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """ @@ -708,60 +717,40 @@ class PurchaseOrderUpload(FileManagementFormView): (field, idx) = form_key.split('-') except ValueError: continue - - if field == self.key_item_select: - if idx not in items: - # Insert into items - items.update({ - idx: { - 'field': form_value, - } - }) - else: - # Update items - items[idx]['field'] = form_value - if field == self.key_quantity_select: - if idx not in items: - # Insert into items - items.update({ - idx: { - 'quantity': form_value, - } - }) - else: - # Update items - items[idx]['quantity'] = form_value - - if field == self.key_price_select: - if idx not in items: - # Insert into items - items.update({ - idx: { - 'purchase_price': form_value, - } - }) - else: - # Update items - items[idx]['purchase_price'] = form_value + if idx not in items: + # Insert into items + items.update({ + idx: { + self.form_field_map[field]: form_value, + } + }) + else: + # Update items + items[idx][self.form_field_map[field]] = form_value # Create PurchaseOrderLineItem instances for purchase_order_item in items.values(): try: - supplier_part = SupplierPart.objects.get(pk=int(purchase_order_item['field'])) + supplier_part = SupplierPart.objects.get(pk=int(purchase_order_item['part'])) except (ValueError, SupplierPart.DoesNotExist): continue - purchase_order_line_item = PurchaseOrderLineItem( - order=order, - part=supplier_part, - quantity=purchase_order_item['quantity'], - purchase_price=purchase_order_item.get('purchase_price', None), - ) - try: - purchase_order_line_item.save() - except IntegrityError: - # PurchaseOrderLineItem already exists - pass + + quantity = purchase_order_item.get('quantity', 0) + if quantity: + purchase_order_line_item = PurchaseOrderLineItem( + order=order, + part=supplier_part, + quantity=quantity, + purchase_price=purchase_order_item.get('purchase_price', None), + reference=purchase_order_item.get('reference', ''), + notes=purchase_order_item.get('notes', ''), + ) + try: + purchase_order_line_item.save() + except IntegrityError: + # PurchaseOrderLineItem already exists + pass return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) From 68b53acbf1253e6c7bdf2b6fc477b12ab0ba9fc6 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 08:07:03 +1000 Subject: [PATCH 158/300] remove old fields from the StockItemTracking model --- InvenTree/stock/api.py | 2 +- InvenTree/stock/forms.py | 7 +++-- .../migrations/0063_auto_20210511_2343.py | 29 +++++++++++++++++++ InvenTree/stock/models.py | 22 -------------- 4 files changed, 34 insertions(+), 26 deletions(-) create mode 100644 InvenTree/stock/migrations/0063_auto_20210511_2343.py diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index b0b6ae1c24..809c354720 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -389,7 +389,7 @@ class StockList(generics.ListCreateAPIView): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - item = serializer.save(user=user, commit=False) + item = serializer.save(user=user) # A location was *not* specified - try to infer it if 'location' not in request.data: diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py index 6d7f8d40ed..92089623f9 100644 --- a/InvenTree/stock/forms.py +++ b/InvenTree/stock/forms.py @@ -437,14 +437,15 @@ class EditStockItemForm(HelperForm): class TrackingEntryForm(HelperForm): - """ Form for creating / editing a StockItemTracking object. + """ + Form for creating / editing a StockItemTracking object. + + Note: 2021-05-11 - This form is not currently used - should delete? """ class Meta: model = StockItemTracking fields = [ - 'title', 'notes', - 'link', ] diff --git a/InvenTree/stock/migrations/0063_auto_20210511_2343.py b/InvenTree/stock/migrations/0063_auto_20210511_2343.py new file mode 100644 index 0000000000..dc8a391cde --- /dev/null +++ b/InvenTree/stock/migrations/0063_auto_20210511_2343.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2 on 2021-05-11 13:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0062_auto_20210511_2151'), + ] + + operations = [ + migrations.RemoveField( + model_name='stockitemtracking', + name='link', + ), + migrations.RemoveField( + model_name='stockitemtracking', + name='quantity', + ), + migrations.RemoveField( + model_name='stockitemtracking', + name='system', + ), + migrations.RemoveField( + model_name='stockitemtracking', + name='title', + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index bae1bc5135..3c702fdbe8 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1626,13 +1626,10 @@ class StockItemTracking(models.Model): Attributes: item: ForeignKey reference to a particular StockItem date: Date that this tracking info was created - title: Title of this tracking info (legacy, no longer used!) tracking_type: The type of tracking information notes: Associated notes (input by user) - link: Optional URL to external page user: The user associated with this tracking info deltas: The changes associated with this history item - quantity: The StockItem quantity at this point in time """ def get_absolute_url(self): @@ -1657,13 +1654,6 @@ class StockItemTracking(models.Model): date = models.DateTimeField(auto_now_add=True, editable=False) - title = models.CharField( - blank=True, null=True, - max_length=250, - verbose_name=_('Title'), - help_text=_('Tracking entry title') - ) - notes = models.CharField( blank=True, null=True, max_length=512, @@ -1671,22 +1661,10 @@ class StockItemTracking(models.Model): help_text=_('Entry notes') ) - link = InvenTreeURLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page for further information')) - user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True) - system = models.BooleanField(default=False) - deltas = models.JSONField(null=True, blank=True) - quantity = models.DecimalField( - max_digits=15, - decimal_places=5, - validators=[MinValueValidator(0)], - default=1, - verbose_name=_('Quantity') - ) - def rename_stock_item_test_result_attachment(instance, filename): From 30ff48d80315a17568fe8e9e95be3187cf1275e5 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 10:09:02 +1000 Subject: [PATCH 159/300] Fixes --- InvenTree/stock/api.py | 3 ++- InvenTree/stock/models.py | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 809c354720..376d04f643 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -389,7 +389,8 @@ class StockList(generics.ListCreateAPIView): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - item = serializer.save(user=user) + # TODO - Save the user who created this item + item = serializer.save() # A location was *not* specified - try to infer it if 'location' not in request.data: diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 3c702fdbe8..28123ebc41 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -981,7 +981,6 @@ class StockItem(MPTTModel): date=datetime.now(), notes=notes, deltas=deltas, - system=True ) entry.save() @@ -1048,7 +1047,7 @@ class StockItem(MPTTModel): new_item.location = location # The item already has a transaction history, don't create a new note - new_item.save(user=user, note=False) + new_item.save(user=user, notes=notes) # Copy entire transaction history new_item.copyHistoryFrom(self) From 3b252b84099dfaaaeba2450080e0038893b29a1f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 10:42:09 +1000 Subject: [PATCH 160/300] Record the user when updating stock items --- InvenTree/stock/serializers.py | 5 ----- InvenTree/stock/views.py | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index d46dc7b3dc..9bcdc5182e 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -366,10 +366,7 @@ class StockTrackingSerializer(InvenTreeModelSerializer): 'date', 'deltas', 'label', - 'link', 'notes', - 'quantity', - 'title', 'tracking_type', 'user', 'user_detail', @@ -378,8 +375,6 @@ class StockTrackingSerializer(InvenTreeModelSerializer): read_only_fields = [ 'date', 'user', - 'system', - 'quantity', 'label', 'tracking_type', ] diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 38757d4cf2..a13f885e80 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -1221,6 +1221,17 @@ class StockItemEditStatus(AjaxUpdateView): form_class = StockForms.EditStockItemStatusForm ajax_form_title = _('Edit Stock Item Status') + def save(self, object, form, **kwargs): + """ + Override the save method, to track the user who updated the model + """ + + item = form.save(commit=False) + + item.save(user=self.request.user) + + return item + class StockItemEdit(AjaxUpdateView): """ @@ -1331,6 +1342,17 @@ class StockItemEdit(AjaxUpdateView): if not owner and not self.request.user.is_superuser: form.add_error('owner', _('Owner is required (ownership control is enabled)')) + def save(self, object, form, **kwargs): + """ + Override the save method, to track the user who updated the model + """ + + item = form.save(commit=False) + + item.save(user=self.request.user) + + return item + class StockItemConvert(AjaxUpdateView): """ From 914db9e913af7b019aaf9b948bffa136107e032f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 10 May 2021 14:23:17 +1000 Subject: [PATCH 161/300] Development docker image - Uses multistage build - Adds a docker compose file for dev --- .github/workflows/docker_build.yaml | 1 + .github/workflows/docker_publish.yaml | 1 + docker/Dockerfile | 9 +++- docker/docker-compose.dev.yml | 70 +++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 docker/docker-compose.dev.yml diff --git a/.github/workflows/docker_build.yaml b/.github/workflows/docker_build.yaml index 26fc69a0f5..ec8bdf7306 100644 --- a/.github/workflows/docker_build.yaml +++ b/.github/workflows/docker_build.yaml @@ -30,6 +30,7 @@ jobs: context: ./docker platforms: linux/amd64,linux/arm64,linux/arm/v7 push: true + target: production repository: inventree/inventree tags: inventree/inventree:latest - name: Image Digest diff --git a/.github/workflows/docker_publish.yaml b/.github/workflows/docker_publish.yaml index c25696d6dd..4a8cef0952 100644 --- a/.github/workflows/docker_publish.yaml +++ b/.github/workflows/docker_publish.yaml @@ -28,4 +28,5 @@ jobs: repository: inventree/inventree tag_with_ref: true dockerfile: ./Dockerfile + target: production platforms: linux/amd64,linux/arm64,linux/arm/v7 diff --git a/docker/Dockerfile b/docker/Dockerfile index c95c2867df..504236c131 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM python:alpine as production +FROM python:alpine as base # GitHub source ARG repository="https://github.com/inventree/InvenTree.git" @@ -73,6 +73,7 @@ RUN pip install --no-cache-dir -U invoke RUN pip install --no-cache-dir -U psycopg2 mysqlclient pgcli mariadb RUN pip install --no-cache-dir -U gunicorn +FROM base as production # Clone source code RUN echo "Downloading InvenTree from ${INVENTREE_REPO}" RUN git clone --branch ${INVENTREE_BRANCH} --depth 1 ${INVENTREE_REPO} ${INVENTREE_SRC_DIR} @@ -97,3 +98,9 @@ WORKDIR ${INVENTREE_SRC_DIR} # Let us begin CMD ["bash", "./start_prod_server.sh"] + +FROM base as dev +# The development image requires the source code to be mounted to /home/inventree/src/ +# So from here, we don't actually "do" anything + +WORKDIR ${INVENTREE_SRC_DIR} diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml new file mode 100644 index 0000000000..b2e64f026a --- /dev/null +++ b/docker/docker-compose.dev.yml @@ -0,0 +1,70 @@ +version: "3.8" + +# Docker compose recipe for InvenTree development server +# - Runs sqlite3 as the database backend +# - Uses built-in django webserver + +# IMPORANT NOTE: +# The InvenTree docker image does not clone source code from git. +# Instead, you must specify *where* the source code is located, +# (on your local machine). +# The django server will auto-detect any code changes and reload the server. + +services: + # InvenTree web server services + # Uses gunicorn as the web server + inventree-server: + container_name: inventree-server + image: inventree/inventree:latest + entrypoint: ./start_dev_server.sh + ports: + - 8000 + depends_on: + - inventree-db + volumes: + # Ensure you specify the location of the 'src' directory at the end of this file + - src:/home/inventree/src + - data:/home/inventree/data + - static:/home/inventree/static + environment: + # Configure a simple sqlite server for development + # Note: You can always change to a different database backend if required! + - INVENTREE_DB_ENGINE=sqlite + - INVENTREE_DB_NAME=inventree + restart: unless-stopped + + # Background worker process handles long-running or periodic tasks + inventree-worker: + container_name: inventree-worker + image: inventree/inventree:latest + entrypoint: ./start_worker.sh + depends_on: + - inventree-db + - inventree-server + volumes: + # Ensure you specify the location of the 'src' directory at the end of this file + - data:/home/inventree/data + - static:/home/inventree/static + environment: + # Configure a simple sqlite server for development + # Note: You can always change to a different database backend if required! + - INVENTREE_DB_ENGINE=sqlite + - INVENTREE_DB_NAME=inventree + restart: unless-stopped + +volumes: + # NOTE: Change /path/to/src to a directory on your local machine, where the InvenTree source code is located + # This directory must conatin the file *manage.py* + # Persistent data, stored external to the container(s) + src: + driver: local + driver_opts: + type: none + o: bind + # This directory specified where InvenTree source code is stored "outside" the docker containers + # Note: This directory must conatin the file *manage.py* + device: /path/to/src + # Uploaded data / media files, shared between containers + data: + # Static files, shared between containers + static: \ No newline at end of file From 3381c5e25753eee420b58b888065ef2d6a5df668 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 20:53:50 +1000 Subject: [PATCH 162/300] Improvements to development docker-compose script - Python packages are installed in a virtual environment within the src dir - This prevents a LONG installation process each time the docker image is rebuilt --- InvenTree/InvenTree/settings.py | 10 ++++++--- docker/Dockerfile | 8 +++++-- docker/docker-compose.dev.yml | 40 +++++++++++++++------------------ docker/start_dev_server.sh | 8 +++++++ 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index cc61748372..5591678e4e 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -430,11 +430,15 @@ It can be specified in config.yaml (or envvar) as either (for example): - django.db.backends.postgresql """ -db_engine = db_config['ENGINE'] +db_engine = db_config['ENGINE'].lower() -if db_engine.lower() in ['sqlite3', 'postgresql', 'mysql']: +# Correct common misspelling +if db_engine == 'sqlite': + db_engine = 'sqlite3' + +if db_engine in ['sqlite3', 'postgresql', 'mysql']: # Prepend the required python module string - db_engine = f'django.db.backends.{db_engine.lower()}' + db_engine = f'django.db.backends.{db_engine}' db_config['ENGINE'] = db_engine db_name = db_config['NAME'] diff --git a/docker/Dockerfile b/docker/Dockerfile index 504236c131..61defc1607 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -86,11 +86,9 @@ COPY gunicorn.conf.py ${INVENTREE_HOME}/gunicorn.conf.py # Copy startup scripts COPY start_prod_server.sh ${INVENTREE_SRC_DIR}/start_prod_server.sh -COPY start_dev_server.sh ${INVENTREE_SRC_DIR}/start_dev_server.sh COPY start_worker.sh ${INVENTREE_SRC_DIR}/start_worker.sh RUN chmod 755 ${INVENTREE_SRC_DIR}/start_prod_server.sh -RUN chmod 755 ${INVENTREE_SRC_DIR}/start_dev_server.sh RUN chmod 755 ${INVENTREE_SRC_DIR}/start_worker.sh # exec commands should be executed from the "src" directory @@ -100,7 +98,13 @@ WORKDIR ${INVENTREE_SRC_DIR} CMD ["bash", "./start_prod_server.sh"] FROM base as dev + # The development image requires the source code to be mounted to /home/inventree/src/ # So from here, we don't actually "do" anything WORKDIR ${INVENTREE_SRC_DIR} + +COPY start_dev_server.sh ${INVENTREE_HOME}/start_dev_server.sh +RUN chmod 755 ${INVENTREE_HOME}/start_dev_server.sh + +CMD ["bash", "/home/inventree/start_dev_server.sh"] diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index b2e64f026a..bde7130c70 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -15,46 +15,46 @@ services: # Uses gunicorn as the web server inventree-server: container_name: inventree-server - image: inventree/inventree:latest - entrypoint: ./start_dev_server.sh + build: + context: . + target: dev ports: - 8000 - depends_on: - - inventree-db volumes: # Ensure you specify the location of the 'src' directory at the end of this file - src:/home/inventree/src - - data:/home/inventree/data - - static:/home/inventree/static environment: # Configure a simple sqlite server for development # Note: You can always change to a different database backend if required! - - INVENTREE_DB_ENGINE=sqlite - - INVENTREE_DB_NAME=inventree + - INVENTREE_DB_ENGINE=sqlite3 + - INVENTREE_DB_NAME=/home/inventree/data/inventree_database.sqlite3 + - INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media + - INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static + - INVENTREE_CONFIG_FILE=/home/inventree/src/config.yaml restart: unless-stopped # Background worker process handles long-running or periodic tasks inventree-worker: container_name: inventree-worker - image: inventree/inventree:latest - entrypoint: ./start_worker.sh - depends_on: - - inventree-db + build: + context: . + target: dev + entrypoint: invoke worker - inventree-server volumes: # Ensure you specify the location of the 'src' directory at the end of this file - - data:/home/inventree/data - - static:/home/inventree/static + - src:/home/inventree/src environment: # Configure a simple sqlite server for development # Note: You can always change to a different database backend if required! - - INVENTREE_DB_ENGINE=sqlite - - INVENTREE_DB_NAME=inventree + - INVENTREE_DB_ENGINE=sqlite3 + - INVENTREE_DB_NAME=/home/inventree/data/inventree_database.sqlite3 + - INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media + - INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static restart: unless-stopped volumes: # NOTE: Change /path/to/src to a directory on your local machine, where the InvenTree source code is located - # This directory must conatin the file *manage.py* # Persistent data, stored external to the container(s) src: driver: local @@ -63,8 +63,4 @@ volumes: o: bind # This directory specified where InvenTree source code is stored "outside" the docker containers # Note: This directory must conatin the file *manage.py* - device: /path/to/src - # Uploaded data / media files, shared between containers - data: - # Static files, shared between containers - static: \ No newline at end of file + device: /path/to/inventree/src diff --git a/docker/start_dev_server.sh b/docker/start_dev_server.sh index c22805b90b..47eb25f9ef 100644 --- a/docker/start_dev_server.sh +++ b/docker/start_dev_server.sh @@ -19,6 +19,14 @@ else cp $INVENTREE_SRC_DIR/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE fi +# Setup a virtual environment +python3 -m venv inventree-docker-dev + +source inventree-docker-dev/bin/activate + +echo "Installing required packages..." +pip install --no-cache-dir -U -r ${INVENTREE_SRC_DIR}/requirements.txt + echo "Starting InvenTree server..." # Wait for the database to be ready From 00c5a883838b5d72aff0e9ff3636a5a4099b99ee Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 21:15:53 +1000 Subject: [PATCH 163/300] Split environment variables out into a .env file - No need to collect "static" file when we are running in DEBUG mode --- .gitignore | 1 + docker/dev-config.env | 7 +++++++ docker/docker-compose.dev.yml | 22 +++++++--------------- docker/start_dev_server.sh | 6 ++---- 4 files changed, 17 insertions(+), 19 deletions(-) create mode 100644 docker/dev-config.env diff --git a/.gitignore b/.gitignore index 54ad8f07b6..7c360a8231 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ var/ *.log local_settings.py *.sqlite3 +*.sqlite3-journal *.backup *.old diff --git a/docker/dev-config.env b/docker/dev-config.env new file mode 100644 index 0000000000..200c3db479 --- /dev/null +++ b/docker/dev-config.env @@ -0,0 +1,7 @@ +INVENTREE_DB_ENGINE=sqlite3 +INVENTREE_DB_NAME=/home/inventree/src/inventree_docker_dev.sqlite3 +INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media +INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static +INVENTREE_CONFIG_FILE=/home/inventree/src/config.yaml +INVENTREE_SECRET_KEY_FILE=/home/inventree/src/secret_key.txt +INVENTREE_DEBUG=true \ No newline at end of file diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index bde7130c70..f03ce45571 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -23,14 +23,10 @@ services: volumes: # Ensure you specify the location of the 'src' directory at the end of this file - src:/home/inventree/src - environment: - # Configure a simple sqlite server for development - # Note: You can always change to a different database backend if required! - - INVENTREE_DB_ENGINE=sqlite3 - - INVENTREE_DB_NAME=/home/inventree/data/inventree_database.sqlite3 - - INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media - - INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static - - INVENTREE_CONFIG_FILE=/home/inventree/src/config.yaml + env_file: + # Environment variables required for the dev server are configured in dev-config.env + - dev-config.env + restart: unless-stopped # Background worker process handles long-running or periodic tasks @@ -44,13 +40,9 @@ services: volumes: # Ensure you specify the location of the 'src' directory at the end of this file - src:/home/inventree/src - environment: - # Configure a simple sqlite server for development - # Note: You can always change to a different database backend if required! - - INVENTREE_DB_ENGINE=sqlite3 - - INVENTREE_DB_NAME=/home/inventree/data/inventree_database.sqlite3 - - INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media - - INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static + env_file: + # Environment variables required for the dev server are configured in dev-config.env + - dev-config.env restart: unless-stopped volumes: diff --git a/docker/start_dev_server.sh b/docker/start_dev_server.sh index 47eb25f9ef..8cf7d10468 100644 --- a/docker/start_dev_server.sh +++ b/docker/start_dev_server.sh @@ -35,16 +35,14 @@ python manage.py wait_for_db sleep 10 -echo "Running InvenTree database migrations and collecting static files..." +echo "Running InvenTree database migrations..." # We assume at this stage that the database is up and running # Ensure that the database schema are up to date python manage.py check || exit 1 python manage.py migrate --noinput || exit 1 python manage.py migrate --run-syncdb || exit 1 -python manage.py prerender || exit 1 -python manage.py collectstatic --noinput || exit 1 python manage.py clearsessions || exit 1 # Launch a development server -python manage.py runserver -a 0.0.0.0:$INVENTREE_WEB_PORT \ No newline at end of file +python manage.py runserver 0.0.0.0:$INVENTREE_WEB_PORT \ No newline at end of file From 530f28ba958336cdaa2e2d1b554de843126e621f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 21:35:54 +1000 Subject: [PATCH 164/300] Fix for running webserver --- docker/docker-compose.dev.yml | 2 +- docker/start_dev_server.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index f03ce45571..d6e6afb665 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -19,7 +19,7 @@ services: context: . target: dev ports: - - 8000 + - 8000:8000 volumes: # Ensure you specify the location of the 'src' directory at the end of this file - src:/home/inventree/src diff --git a/docker/start_dev_server.sh b/docker/start_dev_server.sh index 8cf7d10468..0c1564076a 100644 --- a/docker/start_dev_server.sh +++ b/docker/start_dev_server.sh @@ -45,4 +45,4 @@ python manage.py migrate --run-syncdb || exit 1 python manage.py clearsessions || exit 1 # Launch a development server -python manage.py runserver 0.0.0.0:$INVENTREE_WEB_PORT \ No newline at end of file +python manage.py runserver 0.0.0.0:$INVENTREE_WEB_PORT From 719b1775f2619e2c3e69b752cf969b4a51fb4451 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 12 May 2021 22:12:26 +1000 Subject: [PATCH 165/300] Add entrypoint for running development worker --- docker/Dockerfile | 2 ++ docker/docker-compose.dev.yml | 3 ++- docker/start_dev_worker.sh | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docker/start_dev_worker.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index 61defc1607..3e0a7e1230 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -105,6 +105,8 @@ FROM base as dev WORKDIR ${INVENTREE_SRC_DIR} COPY start_dev_server.sh ${INVENTREE_HOME}/start_dev_server.sh +COPY start_dev_worker.sh ${INVENTREE_HOME}/start_dev_worker.sh RUN chmod 755 ${INVENTREE_HOME}/start_dev_server.sh +RUN chmod 755 ${INVENTREE_HOME}/start_dev_worker.sh CMD ["bash", "/home/inventree/start_dev_server.sh"] diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index d6e6afb665..ddf50135c9 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -35,7 +35,8 @@ services: build: context: . target: dev - entrypoint: invoke worker + entrypoint: /home/inventree/start_dev_worker.sh + depends_on: - inventree-server volumes: # Ensure you specify the location of the 'src' directory at the end of this file diff --git a/docker/start_dev_worker.sh b/docker/start_dev_worker.sh new file mode 100644 index 0000000000..099f447a9c --- /dev/null +++ b/docker/start_dev_worker.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +echo "Starting InvenTree worker..." + +cd $INVENTREE_SRC_DIR + +# Activate virtual environment +source inventree-docker-dev/bin/activate + +sleep 5 + +# Wait for the database to be ready +cd $INVENTREE_MNG_DIR +python manage.py wait_for_db + +sleep 10 + +# Now we can launch the background worker process +python manage.py qcluster From f9f191b5e32d088ff85f1d7cd7639d7c687948b6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 12 May 2021 15:31:35 +0200 Subject: [PATCH 166/300] Inclusion in all tamplates #1574 --- InvenTree/build/templates/build/detail.html | 16 ++++++++-------- .../templates/company/company_base.html | 10 +++++----- .../company/templates/company/detail.html | 6 +++--- .../company/manufacturer_part_base.html | 10 +++++----- .../templates/company/supplier_part_base.html | 19 ++++++++++--------- .../company/supplier_part_detail.html | 8 ++++---- .../order/templates/order/order_base.html | 10 +++++----- .../templates/order/sales_order_base.html | 10 +++++----- InvenTree/part/templates/part/detail.html | 12 ++++++------ 9 files changed, 51 insertions(+), 50 deletions(-) diff --git a/InvenTree/build/templates/build/detail.html b/InvenTree/build/templates/build/detail.html index 9bc1dd77cc..1b4c577b07 100644 --- a/InvenTree/build/templates/build/detail.html +++ b/InvenTree/build/templates/build/detail.html @@ -19,12 +19,12 @@ {% trans "Description" %} - {{ build.title }} + {{ build.title }}{% include "clip.html"%} {% trans "Part" %} - {{ build.part.full_name }} + {{ build.part.full_name }}{% include "clip.html"%} @@ -35,7 +35,7 @@ {% trans "Stock Source" %} {% if build.take_from %} - {{ build.take_from }} + {{ build.take_from }}{% include "clip.html"%} {% else %} {% trans "Stock can be taken from any available location." %} {% endif %} @@ -48,7 +48,7 @@ {% if build.destination %} {{ build.destination }} - + {% include "clip.html"%} {% else %} {% trans "Destination location not specified" %} {% endif %} @@ -68,28 +68,28 @@ {% trans "Batch" %} - {{ build.batch }} + {{ build.batch }}{% include "clip.html"%} {% endif %} {% if build.parent %} {% trans "Parent Build" %} - {{ build.parent }} + {{ build.parent }}{% include "clip.html"%} {% endif %} {% if build.sales_order %} {% trans "Sales Order" %} - {{ build.sales_order }} + {{ build.sales_order }}{% include "clip.html"%} {% endif %} {% if build.link %} {% trans "External Link" %} - {{ build.link }} + {{ build.link }}{% include "clip.html"%} {% endif %} {% if build.issued_by %} diff --git a/InvenTree/company/templates/company/company_base.html b/InvenTree/company/templates/company/company_base.html index 1825132b0e..7012272762 100644 --- a/InvenTree/company/templates/company/company_base.html +++ b/InvenTree/company/templates/company/company_base.html @@ -68,35 +68,35 @@ {% trans "Website" %} - {{ company.website }} + {{ company.website }}{% include "clip.html"%} {% endif %} {% if company.address %} {% trans "Address" %} - {{ company.address }} + {{ company.address }}{% include "clip.html"%} {% endif %} {% if company.phone %} {% trans "Phone" %} - {{ company.phone }} + {{ company.phone }}{% include "clip.html"%} {% endif %} {% if company.email %} {% trans "Email" %} - {{ company.email }} + {{ company.email }}{% include "clip.html"%} {% endif %} {% if company.contact %} {% trans "Contact" %} - {{ company.contact }} + {{ company.contact }}{% include "clip.html"%} {% endif %} diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 9fdd6d0c05..9c3cbfb84a 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -19,20 +19,20 @@ {% trans "Company Name" %} - {{ company.name }} + {{ company.name }}{% include "clip.html"%} {% if company.description %} {% trans "Description" %} - {{ company.description }} + {{ company.description }}{% include "clip.html"%} {% endif %} {% trans "Website" %} - {% if company.website %}{{ company.website }} + {% if company.website %}{{ company.website }}{% include "clip.html"%} {% else %}{% trans "No website specified" %} {% endif %} diff --git a/InvenTree/company/templates/company/manufacturer_part_base.html b/InvenTree/company/templates/company/manufacturer_part_base.html index 441f1f845b..c3a64d9d76 100644 --- a/InvenTree/company/templates/company/manufacturer_part_base.html +++ b/InvenTree/company/templates/company/manufacturer_part_base.html @@ -62,7 +62,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Internal Part" %} {% if part.part %} - {{ part.part.full_name }} + {{ part.part.full_name }}{% include "clip.html"%} {% endif %} @@ -70,24 +70,24 @@ src="{% static 'img/blank_image.png' %}" {% trans "Description" %} - {{ part.description }} + {{ part.description }}{% include "clip.html"%} {% endif %} {% if part.link %} {% trans "External Link" %} - {{ part.link }} + {{ part.link }}{% include "clip.html"%} {% endif %} {% trans "Manufacturer" %} - {{ part.manufacturer.name }} + {{ part.manufacturer.name }}{% include "clip.html"%} {% trans "MPN" %} - {{ part.MPN }} + {{ part.MPN }}{% include "clip.html"%} {% endblock %} diff --git a/InvenTree/company/templates/company/supplier_part_base.html b/InvenTree/company/templates/company/supplier_part_base.html index 3716128bd8..bf6d914f19 100644 --- a/InvenTree/company/templates/company/supplier_part_base.html +++ b/InvenTree/company/templates/company/supplier_part_base.html @@ -61,7 +61,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Internal Part" %} {% if part.part %} - {{ part.part.full_name }} + {{ part.part.full_name }}{% include "clip.html"%} {% endif %} @@ -69,51 +69,52 @@ src="{% static 'img/blank_image.png' %}" {% trans "Description" %} - {{ part.description }} + {{ part.description }}{% include "clip.html"%} {% endif %} {% if part.link %} {% trans "External Link" %} - {{ part.link }} + {{ part.link }}{% include "clip.html"%} {% endif %} {% trans "Supplier" %} - {{ part.supplier.name }} + {{ part.supplier.name }}{% include "clip.html"%} {% trans "SKU" %} - {{ part.SKU }} + {{ part.SKU }}{% include "clip.html"%} {% if part.manufacturer_part.manufacturer %} {% trans "Manufacturer" %} - {{ part.manufacturer_part.manufacturer.name }} + + {{ part.manufacturer_part.manufacturer.name }}{% include "clip.html"%} {% endif %} {% if part.manufacturer_part.MPN %} {% trans "MPN" %} - {{ part.manufacturer_part.MPN }} + {{ part.manufacturer_part.MPN }}{% include "clip.html"%} {% endif %} {% if part.packaging %} {% trans "Packaging" %} - {{ part.packaging }} + {{ part.packaging }}{% include "clip.html"%} {% endif %} {% if part.note %} {% trans "Note" %} - {{ part.note }} + {{ part.note }}{% include "clip.html"%} {% endif %} diff --git a/InvenTree/company/templates/company/supplier_part_detail.html b/InvenTree/company/templates/company/supplier_part_detail.html index 285f81c326..fb73ca06f4 100644 --- a/InvenTree/company/templates/company/supplier_part_detail.html +++ b/InvenTree/company/templates/company/supplier_part_detail.html @@ -28,14 +28,14 @@ {% trans "External Link" %}{{ part.link }} {% endif %} {% if part.description %} - {% trans "Description" %}{{ part.description }} + {% trans "Description" %}{{ part.description }}{% include "clip.html"%} {% endif %} {% if part.manufacturer %} - {% trans "Manufacturer" %}{{ part.manufacturer }} - {% trans "MPN" %}{{ part.MPN }} + {% trans "Manufacturer" %}{{ part.manufacturer }}{% include "clip.html"%} + {% trans "MPN" %}{{ part.MPN }}{% include "clip.html"%} {% endif %} {% if part.note %} - {% trans "Note" %}{{ part.note }} + {% trans "Note" %}{{ part.note }}{% include "clip.html"%} {% endif %} diff --git a/InvenTree/order/templates/order/order_base.html b/InvenTree/order/templates/order/order_base.html index b29b62a4ad..642f866506 100644 --- a/InvenTree/order/templates/order/order_base.html +++ b/InvenTree/order/templates/order/order_base.html @@ -33,7 +33,7 @@ src="{% static 'img/blank_image.png' %}" {% endif %}
    -

    {{ order.description }}

    +

    {{ order.description }}{% include "clip.html"%}

    + + +
    diff --git a/InvenTree/templates/version.html b/InvenTree/templates/version.html new file mode 100644 index 0000000000..c8ec6862b6 --- /dev/null +++ b/InvenTree/templates/version.html @@ -0,0 +1,5 @@ +# Version Information:{% load inventree_extras %} +InvenTree-Version: {% inventree_version %} +Django Version: {% django_version %} +{% inventree_commit_hash as hash %}{% if hash %}Commit Hash: {{ hash }}{% endif %} +{% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {{ commit_date }}{% endif %} \ No newline at end of file From 5077419b689dd54da8d20371a1f800e13333b708 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 13 May 2021 00:20:51 +0200 Subject: [PATCH 171/300] fewer js-functions --- .../static/script/inventree/inventree.js | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/InvenTree/InvenTree/static/script/inventree/inventree.js b/InvenTree/InvenTree/static/script/inventree/inventree.js index afc2a80755..4b43b342af 100644 --- a/InvenTree/InvenTree/static/script/inventree/inventree.js +++ b/InvenTree/InvenTree/static/script/inventree/inventree.js @@ -1,40 +1,31 @@ -function attachClipboard(selector) { +function attachClipboard(selector, containerselector, textElement) { + // set container + if (containerselector){ + containerselector = document.getElementById(containerselector); + } else { + containerselector = document.body; + } - var cis = new ClipboardJS(selector, { - text: function(trigger) { - var content = trigger.parentElement.parentElement.textContent; - - return content.trim(); + // set text-function + if (textElement){ + text = function() { + return document.getElementById(textElement).textContent; } + } else { + text = function() { + var content = trigger.parentElement.parentElement.textContent;return content.trim(); + } + } + + // create Clipboard + var cis = new ClipboardJS(selector, { + text: text, + container: containerselector }); console.log(cis); } -function attachmodalClipboard(selector) { - - new ClipboardJS(selector, { - text: function(trigger) { - var content = trigger.parentElement.parentElement.textContent; - return content.trim(); - }, - container: document.getElementById('modal-about') - }); -} - - -function AboutClipboard(selector) { - - new ClipboardJS(selector, { - text: function() { - console.log('about'); - return document.getElementById('about-copy-text').textContent; - }, - container: document.getElementById('modal-about') - }); -} - - function inventreeDocReady() { /* Run this function when the HTML document is loaded. * This will be called for every page that extends "base.html" @@ -88,8 +79,8 @@ function inventreeDocReady() { // Initialize clipboard-buttons attachClipboard('.clip-btn'); - attachmodalClipboard('.clip-btn'); - AboutClipboard('.clip-btn-version'); + attachClipboard('.clip-btn', 'modal-about'); // modals + attachClipboard('.clip-btn-version', 'modal-about', 'about-copy-text'); // version-text } From ba3f3108d7c7204c23f8ae5d6317c167668722b8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 13 May 2021 00:21:42 +0200 Subject: [PATCH 172/300] missing translation --- InvenTree/templates/about.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/templates/about.html b/InvenTree/templates/about.html index 7d40388d3b..f190ab2755 100644 --- a/InvenTree/templates/about.html +++ b/InvenTree/templates/about.html @@ -77,7 +77,7 @@ - + From 6de44a59217d167d7547c790a39819446ed2c85b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 13 May 2021 13:23:51 +1000 Subject: [PATCH 173/300] Adds a "filename_template" field to reports - Allows users to define the naming scheme for generated reports - Templated, can use any context variable already available to the report instance - Adds some more context variables to various reports --- InvenTree/report/api.py | 10 ++++- .../migrations/0016_auto_20210513_1303.py | 38 +++++++++++++++++++ InvenTree/report/models.py | 26 ++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 InvenTree/report/migrations/0016_auto_20210513_1303.py diff --git a/InvenTree/report/api.py b/InvenTree/report/api.py index 351a988601..f09a52f272 100644 --- a/InvenTree/report/api.py +++ b/InvenTree/report/api.py @@ -208,16 +208,24 @@ class ReportPrintMixin: # In debug mode, generate single HTML output, rather than PDF debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') + # Start with a default report name + report_name = "report.pdf" + # Merge one or more PDF files into a single download for item in items_to_print: report = self.get_object() report.object_to_print = item + report_name = report.generate_filename(request) + if debug_mode: outputs.append(report.render_as_string(request)) else: outputs.append(report.render(request)) + if not report_name.endswith('.pdf'): + report_name += '.pdf' + if debug_mode: """ Contatenate all rendered templates into a single HTML string, @@ -248,7 +256,7 @@ class ReportPrintMixin: return InvenTree.helpers.DownloadFile( pdf, - 'inventree_report.pdf', + report_name, content_type='application/pdf' ) diff --git a/InvenTree/report/migrations/0016_auto_20210513_1303.py b/InvenTree/report/migrations/0016_auto_20210513_1303.py new file mode 100644 index 0000000000..5b1e950dea --- /dev/null +++ b/InvenTree/report/migrations/0016_auto_20210513_1303.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2 on 2021-05-13 03:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('report', '0015_auto_20210403_1837'), + ] + + operations = [ + migrations.AddField( + model_name='billofmaterialsreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='buildreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='purchaseorderreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='salesorderreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='testreport', + name='filename_pattern', + field=models.CharField(default='report.pdf', help_text='Pattern for generating report filenames', max_length=100, verbose_name='Filename Pattern'), + ), + ] diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index fa7ae2b271..dfb7c09679 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -16,6 +16,7 @@ from django.conf import settings from django.core.exceptions import ValidationError, FieldError from django.template.loader import render_to_string +from django.template import Template, Context from django.core.files.storage import FileSystemStorage from django.core.validators import FileExtensionValidator @@ -224,6 +225,7 @@ class ReportTemplateBase(ReportBase): All context to be passed to the renderer. """ + # Generate custom context data based on the particular report subclass context = self.get_context_data(request) context['base_url'] = common.models.InvenTreeSetting.get_setting('INVENTREE_BASE_URL') @@ -238,9 +240,22 @@ class ReportTemplateBase(ReportBase): return context + def generate_filename(self, request, **kwargs): + """ + Generate a filename for this report + """ + + template_string = Template(self.filename_pattern) + + ctx = self.context(request) + + context = Context(ctx) + + return template_string.render(context) + def render_as_string(self, request, **kwargs): """ - Render the report to a HTML stiring. + Render the report to a HTML string. Useful for debug mode (viewing generated code) """ @@ -269,6 +284,13 @@ class ReportTemplateBase(ReportBase): self.context(request), **kwargs) + filename_pattern = models.CharField( + default="report.pdf", + verbose_name=_('Filename Pattern'), + help_text=_('Pattern for generating report filenames'), + max_length=100, + ) + enabled = models.BooleanField( default=True, verbose_name=_('Enabled'), @@ -326,6 +348,7 @@ class TestReport(ReportTemplateBase): return { 'stock_item': stock_item, + 'serial': stock_item.serial, 'part': stock_item.part, 'results': stock_item.testResultMap(include_installed=self.include_installed), 'result_list': stock_item.testResultList(include_installed=self.include_installed) @@ -367,6 +390,7 @@ class BuildReport(ReportTemplateBase): 'bom_items': my_build.part.get_bom_items(), 'reference': my_build.reference, 'quantity': my_build.quantity, + 'title': str(my_build), } From 82a3d9ca967f80d25e9bf09fe56d79acd81e779f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 13 May 2021 13:40:40 +1000 Subject: [PATCH 174/300] Implements custom naming for generated labels --- InvenTree/label/api.py | 9 +++++++- .../migrations/0007_auto_20210513_1327.py | 23 +++++++++++++++++++ InvenTree/label/models.py | 22 ++++++++++++++++++ InvenTree/report/models.py | 1 + 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 InvenTree/label/migrations/0007_auto_20210513_1327.py diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py index fc082e4a50..8522857e30 100644 --- a/InvenTree/label/api.py +++ b/InvenTree/label/api.py @@ -63,16 +63,23 @@ class LabelPrintMixin: # In debug mode, generate single HTML output, rather than PDF debug_mode = common.models.InvenTreeSetting.get_setting('REPORT_DEBUG_MODE') + label_name = "label.pdf" + # Merge one or more PDF files into a single download for item in items_to_print: label = self.get_object() label.object_to_print = item + label_name = label.generate_filename(request) + if debug_mode: outputs.append(label.render_as_string(request)) else: outputs.append(label.render(request)) + if not label_name.endswith(".pdf"): + label_name += ".pdf" + if debug_mode: """ Contatenate all rendered templates into a single HTML string, @@ -103,7 +110,7 @@ class LabelPrintMixin: return InvenTree.helpers.DownloadFile( pdf, - 'inventree_label.pdf', + label_name, content_type='application/pdf' ) diff --git a/InvenTree/label/migrations/0007_auto_20210513_1327.py b/InvenTree/label/migrations/0007_auto_20210513_1327.py new file mode 100644 index 0000000000..d49c83c92b --- /dev/null +++ b/InvenTree/label/migrations/0007_auto_20210513_1327.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2 on 2021-05-13 03:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('label', '0006_auto_20210222_1535'), + ] + + operations = [ + migrations.AddField( + model_name='stockitemlabel', + name='filename_pattern', + field=models.CharField(default='label.pdf', help_text='Pattern for generating label filenames', max_length=100, verbose_name='Filename Pattern'), + ), + migrations.AddField( + model_name='stocklocationlabel', + name='filename_pattern', + field=models.CharField(default='label.pdf', help_text='Pattern for generating label filenames', max_length=100, verbose_name='Filename Pattern'), + ), + ] diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index 71ccc73ac9..a5d8314193 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -15,6 +15,7 @@ from django.db import models from django.core.validators import FileExtensionValidator, MinValueValidator from django.core.exceptions import ValidationError, FieldError +from django.template import Template, Context from django.template.loader import render_to_string from django.utils.translation import gettext_lazy as _ @@ -138,6 +139,13 @@ class LabelTemplate(models.Model): validators=[MinValueValidator(2)] ) + filename_pattern = models.CharField( + default="label.pdf", + verbose_name=_('Filename Pattern'), + help_text=_('Pattern for generating label filenames'), + max_length=100, + ) + @property def template_name(self): """ @@ -162,6 +170,19 @@ class LabelTemplate(models.Model): return {} + def generate_filename(self, request, **kwargs): + """ + Generate a filename for this label + """ + + template_string = Template(self.filename_pattern) + + ctx = self.context(request) + + context = Context(ctx) + + return template_string.render(context) + def context(self, request): """ Provides context data to the template. @@ -201,6 +222,7 @@ class LabelTemplate(models.Model): self.template_name, base_url=request.build_absolute_uri("/"), presentational_hints=True, + filename=self.generate_filename(request), **kwargs ) diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py index dfb7c09679..ecb4d91492 100644 --- a/InvenTree/report/models.py +++ b/InvenTree/report/models.py @@ -278,6 +278,7 @@ class ReportTemplateBase(ReportBase): self.template_name, base_url=request.build_absolute_uri("/"), presentational_hints=True, + filename=self.generate_filename(request), **kwargs) return wp.render_to_response( From e382f2a57ec1a459086c51ce4faa9b690e7330b9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 13 May 2021 15:46:27 +0200 Subject: [PATCH 175/300] fixing bug from refactor --- InvenTree/InvenTree/static/script/inventree/inventree.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/InvenTree/InvenTree/static/script/inventree/inventree.js b/InvenTree/InvenTree/static/script/inventree/inventree.js index 4b43b342af..1a6fdec47a 100644 --- a/InvenTree/InvenTree/static/script/inventree/inventree.js +++ b/InvenTree/InvenTree/static/script/inventree/inventree.js @@ -12,7 +12,7 @@ function attachClipboard(selector, containerselector, textElement) { return document.getElementById(textElement).textContent; } } else { - text = function() { + text = function(trigger) { var content = trigger.parentElement.parentElement.textContent;return content.trim(); } } @@ -22,7 +22,6 @@ function attachClipboard(selector, containerselector, textElement) { text: text, container: containerselector }); - console.log(cis); } @@ -81,7 +80,6 @@ function inventreeDocReady() { attachClipboard('.clip-btn'); attachClipboard('.clip-btn', 'modal-about'); // modals attachClipboard('.clip-btn-version', 'modal-about', 'about-copy-text'); // version-text - } function isFileTransfer(transfer) { From f2e9f58f1b3916f058e42fcbfa29c3b3e0539b41 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 13 May 2021 15:47:42 -0400 Subject: [PATCH 176/300] Added purchase price range and average to BOM items/view --- InvenTree/part/api.py | 9 ++++++++- InvenTree/part/serializers.py | 9 +++++++++ InvenTree/templates/js/bom.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index de6ac5f273..659976a0b0 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals from django_filters.rest_framework import DjangoFilterBackend from django.http import JsonResponse -from django.db.models import Q, F, Count +from django.db.models import Q, F, Count, Min, Max, Avg from django.utils.translation import ugettext_lazy as _ from rest_framework import status @@ -877,6 +877,13 @@ class BomList(generics.ListCreateAPIView): else: queryset = queryset.exclude(pk__in=pks) + # Annotate with purchase prices + queryset = queryset.annotate( + purchase_price_min=Min('sub_part__stock_items__purchase_price'), + purchase_price_max=Max('sub_part__stock_items__purchase_price'), + purchase_price_avg=Avg('sub_part__stock_items__purchase_price'), + ) + return queryset filter_backends = [ diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 7ab385249c..8c2d72f43d 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -367,6 +367,12 @@ class BomItemSerializer(InvenTreeModelSerializer): validated = serializers.BooleanField(read_only=True, source='is_line_valid') + purchase_price_min = serializers.FloatField() + + purchase_price_max = serializers.FloatField() + + purchase_price_avg = serializers.FloatField() + def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. # This saves a bunch of database requests @@ -410,6 +416,9 @@ class BomItemSerializer(InvenTreeModelSerializer): 'sub_part_detail', # 'price_range', 'validated', + 'purchase_price_min', + 'purchase_price_max', + 'purchase_price_avg', ] diff --git a/InvenTree/templates/js/bom.js b/InvenTree/templates/js/bom.js index 462db6eba4..c97d8b30e5 100644 --- a/InvenTree/templates/js/bom.js +++ b/InvenTree/templates/js/bom.js @@ -243,6 +243,35 @@ function loadBomTable(table, options) { } }); + cols.push( + { + field: 'purchase_price_range', + title: '{% trans "Purchase Price Range" %}', + searchable: false, + sortable: true, + formatter: function(value, row, index, field) { + var purchase_price_range = 0; + + if (row.purchase_price_min > 0) { + if (row.purchase_price_min >= row.purchase_price_max) { + purchase_price_range = row.purchase_price_min; + } else { + purchase_price_range = row.purchase_price_min + " - " + row.purchase_price_max; + } + } + + return purchase_price_range; + }, + }); + + cols.push( + { + field: 'purchase_price_avg', + title: '{% trans "Purchase Price Average" %}', + searchable: false, + sortable: true, + }); + /* // TODO - Re-introduce the pricing column at a later stage, From 22249206d24206c5073e7d7ba33f9c0ba0d25fd5 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 13 May 2021 16:06:57 -0400 Subject: [PATCH 177/300] Fixed duplicate check --- InvenTree/common/views.py | 5 +++-- .../order/templates/order/order_wizard/match_fields.html | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index fa605c2b80..99862f5c08 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -209,6 +209,7 @@ class FileManagementFormView(MultiStepFormView): context.update({'columns': self.columns}) # Load extra context data + print(self.extra_context_data) for key, items in self.extra_context_data.items(): context.update({key: items}) @@ -449,8 +450,8 @@ class FileManagementFormView(MultiStepFormView): if guess: n = list(self.column_selections.values()).count(self.column_selections[col]) - if n > 1: - duplicates.append(col) + if n > 1 and self.column_selections[col] not in duplicates: + duplicates.append(self.column_selections[col]) # Store extra context data self.extra_context_data = { diff --git a/InvenTree/order/templates/order/order_wizard/match_fields.html b/InvenTree/order/templates/order/order_wizard/match_fields.html index 4ff7b6a963..cd81142341 100644 --- a/InvenTree/order/templates/order/order_wizard/match_fields.html +++ b/InvenTree/order/templates/order/order_wizard/match_fields.html @@ -55,7 +55,7 @@ {{ col }} {% for duplicate in duplicates %} - {% if duplicate == col.name %} + {% if duplicate == col.value %} From a64ab5956b2a1daec62fc8789ce600250882d78f Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 13 May 2021 16:07:57 -0400 Subject: [PATCH 178/300] Removed leftover print --- InvenTree/common/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/InvenTree/common/views.py b/InvenTree/common/views.py index 99862f5c08..857b6b2c51 100644 --- a/InvenTree/common/views.py +++ b/InvenTree/common/views.py @@ -209,7 +209,6 @@ class FileManagementFormView(MultiStepFormView): context.update({'columns': self.columns}) # Load extra context data - print(self.extra_context_data) for key, items in self.extra_context_data.items(): context.update({key: items}) From 32d0f3039de910b8e3c90164c5c80da84907e541 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 13 May 2021 16:17:45 -0400 Subject: [PATCH 179/300] Obviously new float fields should be read-only... --- InvenTree/part/serializers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 8c2d72f43d..2316f2f18b 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -367,11 +367,11 @@ class BomItemSerializer(InvenTreeModelSerializer): validated = serializers.BooleanField(read_only=True, source='is_line_valid') - purchase_price_min = serializers.FloatField() + purchase_price_min = serializers.FloatField(read_only=True) - purchase_price_max = serializers.FloatField() + purchase_price_max = serializers.FloatField(read_only=True) - purchase_price_avg = serializers.FloatField() + purchase_price_avg = serializers.FloatField(read_only=True) def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. From bca2f4a07b95c448a21e49ebfe66b600588d8d5d Mon Sep 17 00:00:00 2001 From: Nigel Date: Thu, 15 Apr 2021 15:21:13 -0600 Subject: [PATCH 180/300] feat(sales_order): Stock Items show the PO number Stock items show the PO number that they were purchased on when being viewed in the sales order allocation modal and when viewing the sales order details. --- InvenTree/order/models.py | 3 ++ InvenTree/order/serializers.py | 2 ++ .../templates/order/sales_order_detail.html | 29 +++++++++++++++++-- InvenTree/order/views.py | 2 +- InvenTree/stock/models.py | 6 ++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index 5305038b4f..fb169e0536 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -826,6 +826,9 @@ class SalesOrderAllocation(models.Model): else: return "" + def get_po(self): + return self.item.purchase_order + def complete_allocation(self, user): """ Complete this allocation (called when the parent SalesOrder is marked as "shipped"): diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 062e8986b2..6091140313 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -235,6 +235,7 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer): location_path = serializers.CharField(source='get_location_path') location_id = serializers.IntegerField(source='get_location') serial = serializers.CharField(source='get_serial') + po = serializers.CharField(source='get_po') quantity = serializers.FloatField() class Meta: @@ -247,6 +248,7 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer): 'quantity', 'location_id', 'location_path', + 'po', 'item', ] diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 72b7d63911..a90e61bff9 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -87,6 +87,9 @@ function showAllocationSubTable(index, row, element) { return renderLink(row.location_path, `/stock/location/${row.location_id}/`); }, }, + { + field: 'po' + }, { field: 'buttons', title: '{% trans "Actions" %}', @@ -159,9 +162,12 @@ function showFulfilledSubTable(index, row, element) { text = `{% trans "Quantity" %}: ${row.quantity}`; } - return renderLink(text, `/stock/item/${row.pk}/`); + return renderLink(text, `/stock/item/${row.pk}/`); }, - } + }, + { + field: 'po' + }, ], }); } @@ -271,6 +277,25 @@ $("#so-lines-table").inventreeTable({ field: 'notes', title: '{% trans "Notes" %}', }, + { + field: 'po', + title: '{% trans "PO" %}', + formatter: function(value, row, index, field) { + var po_name = ""; + if (row.allocated) { + row.allocations.forEach(function(allocation) { + if (allocation.po != po_name) { + if (po_name) { + po_name = "-"; + } else { + po_name = allocation.po + } + } + }) + } + return `
    ` + po_name + `
    `; + } + }, {% if order.status == SalesOrderStatus.PENDING %} { field: 'buttons', diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index cf79746f0d..c8ec42d3e7 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -90,7 +90,7 @@ class SalesOrderDetail(InvenTreeRoleMixin, DetailView): """ Detail view for a SalesOrder object """ context_object_name = 'order' - queryset = SalesOrder.objects.all().prefetch_related('lines') + queryset = SalesOrder.objects.all().prefetch_related('lines__allocations__item__purchase_order') template_name = 'order/sales_order_detail.html' diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 28123ebc41..88f8dd081c 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1370,6 +1370,12 @@ class StockItem(MPTTModel): if self.location: s += ' @ {loc}'.format(loc=self.location.name) + if self.purchase_order: + s += " ({pre}{po})".format( + pre=helpers.getSetting("PURCHASEORDER_REFERENCE_PREFIX"), + po=self.purchase_order, + ) + return s @transaction.atomic From 68f5ec8b6a9f54e8273627e2495edd7fbb169179 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 13 May 2021 17:09:52 -0400 Subject: [PATCH 181/300] Added currency conversion --- InvenTree/part/api.py | 42 +++++++++++++++++++++++++++++++++++ InvenTree/part/serializers.py | 7 +++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 659976a0b0..5b82a168cf 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -15,6 +15,10 @@ from rest_framework.response import Response from rest_framework import filters, serializers from rest_framework import generics +from djmoney.money import Money +from djmoney.contrib.exchange.models import convert_money +from djmoney.contrib.exchange.exceptions import MissingRate + from django.conf.urls import url, include from django.urls import reverse @@ -24,6 +28,7 @@ from .models import PartAttachment, PartTestTemplate from .models import PartSellPriceBreak from .models import PartCategoryParameterTemplate +from common.models import InvenTreeSetting from build.models import Build from . import serializers as part_serializers @@ -882,8 +887,45 @@ class BomList(generics.ListCreateAPIView): purchase_price_min=Min('sub_part__stock_items__purchase_price'), purchase_price_max=Max('sub_part__stock_items__purchase_price'), purchase_price_avg=Avg('sub_part__stock_items__purchase_price'), + purchase_price_currency=F('sub_part__stock_items__purchase_price_currency'), ) + # Convert prices to default currency (using backend conversion rates) + for item in queryset: + # Get default currency from settings + default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') + + if default_currency: + if item.purchase_price_min: + # Convert minimum + try: + # Get adjusted price + purchase_price_adjusted = convert_money(Money(item.purchase_price_min, item.purchase_price_currency), default_currency) + # Update queryset + item.purchase_price_min = purchase_price_adjusted + except MissingRate: + pass + + if item.purchase_price_max: + # Convert maximum + try: + # Get adjusted price + purchase_price_adjusted = convert_money(Money(item.purchase_price_max, item.purchase_price_currency), default_currency) + # Update queryset + item.purchase_price_max = purchase_price_adjusted + except MissingRate: + pass + + if item.purchase_price_avg: + # Convert average + try: + # Get adjusted price + purchase_price_adjusted = convert_money(Money(item.purchase_price_avg, item.purchase_price_currency), default_currency) + # Update queryset + item.purchase_price_avg = purchase_price_adjusted + except MissingRate: + pass + return queryset filter_backends = [ diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 2316f2f18b..096d072981 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -12,6 +12,7 @@ from InvenTree.serializers import (InvenTreeAttachmentSerializerField, from InvenTree.status_codes import BuildStatus, PurchaseOrderStatus from rest_framework import serializers from sql_util.utils import SubqueryCount, SubquerySum +from djmoney.contrib.django_rest_framework import MoneyField from stock.models import StockItem from .models import (BomItem, Part, PartAttachment, PartCategory, @@ -367,11 +368,11 @@ class BomItemSerializer(InvenTreeModelSerializer): validated = serializers.BooleanField(read_only=True, source='is_line_valid') - purchase_price_min = serializers.FloatField(read_only=True) + purchase_price_min = MoneyField(max_digits=10, decimal_places=4, read_only=True) - purchase_price_max = serializers.FloatField(read_only=True) + purchase_price_max = MoneyField(max_digits=10, decimal_places=4, read_only=True) - purchase_price_avg = serializers.FloatField(read_only=True) + purchase_price_avg = MoneyField(max_digits=10, decimal_places=4, read_only=True) def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. From f76bc5a7b8661a371669c21959f65e44b252cb45 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 14 May 2021 12:38:38 +1000 Subject: [PATCH 182/300] Add debug mode and database backend as info to the "stats" dialog --- .../part/templatetags/inventree_extras.py | 24 +++++++++++++++++++ InvenTree/templates/stats.html | 13 ++++++++++ 2 files changed, 37 insertions(+) diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 2c588a81e5..799ad8788b 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -1,7 +1,14 @@ +# -*- coding: utf-8 -*- + """ This module provides template tags for extra functionality over and above the built-in Django tags. """ + import os +import django + +from django.utils.translation import ugettext_lazy as _ +from django.conf import settings as djangosettings from django import template from django.urls import reverse @@ -67,6 +74,23 @@ def part_allocation_count(build, part, *args, **kwargs): return InvenTree.helpers.decimal2string(build.getAllocatedQuantity(part)) +@register.simple_tag() +def inventree_in_debug_mode(*args, **kwargs): + """ Return True if the server is running in DEBUG mode """ + + return djangosettings.DEBUG + +@register.simple_tag() +def inventree_db_engine(*args, **kwargs): + """ Return the InvenTree database backend e.g. 'postgresql' """ + + db = djangosettings.DATABASES['default'] + + engine = db.get('ENGINE', _('Unknown database')) + + engine = engine.replace('django.db.backends.', '') + + return engine @register.simple_tag() def inventree_instance_name(*args, **kwargs): diff --git a/InvenTree/templates/stats.html b/InvenTree/templates/stats.html index eff9c4504f..1598d45d26 100644 --- a/InvenTree/templates/stats.html +++ b/InvenTree/templates/stats.html @@ -13,6 +13,19 @@ {% trans "Instance Name" %} {% inventree_instance_name %} + + + {% trans "Database" %} + {% inventree_db_engine %} + + {% inventree_in_debug_mode as debug_mode %} + {% if debug_mode %} + + + {% trans "Debug Mode" %} + {% trans "Server is running in debug mode" %} + + {% endif %} {% if user.is_staff %} From 7deea1ec00303d9943bc4185d6ad0a0e1e04dd25 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 14 May 2021 12:40:42 +1000 Subject: [PATCH 183/300] Style fixes --- InvenTree/part/templatetags/inventree_extras.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 799ad8788b..e8743028a0 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -5,7 +5,6 @@ over and above the built-in Django tags. """ import os -import django from django.utils.translation import ugettext_lazy as _ from django.conf import settings as djangosettings @@ -74,12 +73,14 @@ def part_allocation_count(build, part, *args, **kwargs): return InvenTree.helpers.decimal2string(build.getAllocatedQuantity(part)) + @register.simple_tag() def inventree_in_debug_mode(*args, **kwargs): """ Return True if the server is running in DEBUG mode """ return djangosettings.DEBUG + @register.simple_tag() def inventree_db_engine(*args, **kwargs): """ Return the InvenTree database backend e.g. 'postgresql' """ @@ -92,6 +93,7 @@ def inventree_db_engine(*args, **kwargs): return engine + @register.simple_tag() def inventree_instance_name(*args, **kwargs): """ Return the InstanceName associated with the current database """ From 30a2194fe1b121c5f64345a8c245a31614d424ba Mon Sep 17 00:00:00 2001 From: Nigel Date: Fri, 14 May 2021 13:24:13 -0600 Subject: [PATCH 184/300] feat(admin): Show the line items on the PO on the Admin Site --- InvenTree/order/admin.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/InvenTree/order/admin.py b/InvenTree/order/admin.py index 4519f8a2a9..1e7b20e5a1 100644 --- a/InvenTree/order/admin.py +++ b/InvenTree/order/admin.py @@ -13,6 +13,10 @@ from .models import SalesOrder, SalesOrderLineItem from .models import SalesOrderAllocation +class PurchaseOrderLineItemInlineAdmin(admin.StackedInline): + model = PurchaseOrderLineItem + + class PurchaseOrderAdmin(ImportExportModelAdmin): list_display = ( @@ -29,6 +33,10 @@ class PurchaseOrderAdmin(ImportExportModelAdmin): 'description', ] + inlines = [ + PurchaseOrderLineItemInlineAdmin + ] + class SalesOrderAdmin(ImportExportModelAdmin): From 1940fd5199f34e91b6df6b17dc8a8adbd909efbf Mon Sep 17 00:00:00 2001 From: eeintech Date: Fri, 14 May 2021 16:16:23 -0400 Subject: [PATCH 185/300] Now processing currencies --- InvenTree/part/api.py | 70 ++++++++++++++++++++--------------- InvenTree/part/serializers.py | 43 +++++++++++++++++++-- InvenTree/templates/js/bom.js | 13 ------- 3 files changed, 79 insertions(+), 47 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 5b82a168cf..065eca30c6 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -887,44 +887,54 @@ class BomList(generics.ListCreateAPIView): purchase_price_min=Min('sub_part__stock_items__purchase_price'), purchase_price_max=Max('sub_part__stock_items__purchase_price'), purchase_price_avg=Avg('sub_part__stock_items__purchase_price'), - purchase_price_currency=F('sub_part__stock_items__purchase_price_currency'), ) - # Convert prices to default currency (using backend conversion rates) - for item in queryset: + # Get values for currencies + currencies = queryset.annotate( + purchase_price_currency=F('sub_part__stock_items__purchase_price_currency'), + ).values('pk', 'sub_part', 'purchase_price_currency') + + def convert_price(price, currency, decimal_places=4): + """ Convert price field, returns Money field """ + + price_adjusted = None + # Get default currency from settings default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') - if default_currency: - if item.purchase_price_min: - # Convert minimum + if price: + if currency and default_currency: try: # Get adjusted price - purchase_price_adjusted = convert_money(Money(item.purchase_price_min, item.purchase_price_currency), default_currency) - # Update queryset - item.purchase_price_min = purchase_price_adjusted + price_adjusted = convert_money(Money(price, currency), default_currency) except MissingRate: - pass - - if item.purchase_price_max: - # Convert maximum - try: - # Get adjusted price - purchase_price_adjusted = convert_money(Money(item.purchase_price_max, item.purchase_price_currency), default_currency) - # Update queryset - item.purchase_price_max = purchase_price_adjusted - except MissingRate: - pass - - if item.purchase_price_avg: - # Convert average - try: - # Get adjusted price - purchase_price_adjusted = convert_money(Money(item.purchase_price_avg, item.purchase_price_currency), default_currency) - # Update queryset - item.purchase_price_avg = purchase_price_adjusted - except MissingRate: - pass + # No conversion rate set + price_adjusted = Money(price, currency) + else: + # Currency exists + if currency: + price_adjusted = Money(price, currency) + # Default currency exists + if default_currency: + price_adjusted = Money(price, default_currency) + + if price_adjusted and decimal_places: + price_adjusted.decimal_places = decimal_places + + return price_adjusted + + # Convert prices to default currency (using backend conversion rates) + for bom_item in queryset: + # Find associated currency (select first found) + purchase_price_currency = None + for currency_item in currencies: + if currency_item['pk'] == bom_item.pk and currency_item['sub_part'] == bom_item.sub_part: + purchase_price_currency = currency_item['purchase_price_currency'] + break + # Convert prices + bom_item.purchase_price_min = convert_price(bom_item.purchase_price_min, purchase_price_currency) + bom_item.purchase_price_max = convert_price(bom_item.purchase_price_max, purchase_price_currency) + bom_item.purchase_price_avg = convert_price(bom_item.purchase_price_avg, purchase_price_currency) return queryset diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 096d072981..868997915b 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -368,11 +368,13 @@ class BomItemSerializer(InvenTreeModelSerializer): validated = serializers.BooleanField(read_only=True, source='is_line_valid') - purchase_price_min = MoneyField(max_digits=10, decimal_places=4, read_only=True) + purchase_price_min = MoneyField(max_digits=10, decimal_places=6, read_only=True) - purchase_price_max = MoneyField(max_digits=10, decimal_places=4, read_only=True) - - purchase_price_avg = MoneyField(max_digits=10, decimal_places=4, read_only=True) + purchase_price_max = MoneyField(max_digits=10, decimal_places=6, read_only=True) + + purchase_price_avg = serializers.SerializerMethodField() + + purchase_price_range = serializers.SerializerMethodField() def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. @@ -401,6 +403,38 @@ class BomItemSerializer(InvenTreeModelSerializer): queryset = queryset.prefetch_related('sub_part__supplier_parts__pricebreaks') return queryset + def get_purchase_price_range(self, obj): + """ Return purchase price range """ + + if obj.purchase_price_min and not obj.purchase_price_max: + # Get price range + purchase_price_range = str(obj.purchase_price_max) + elif not obj.purchase_price_min and obj.purchase_price_max: + # Get price range + purchase_price_range = str(obj.purchase_price_max) + elif obj.purchase_price_min and obj.purchase_price_max: + # Get price range + if obj.purchase_price_min >= obj.purchase_price_max: + # If min > max: use min only + purchase_price_range = str(obj.purchase_price_min) + else: + purchase_price_range = str(obj.purchase_price_min) + " - " + str(obj.purchase_price_max) + else: + purchase_price_range = '-' + + return purchase_price_range + + def get_purchase_price_avg(self, obj): + """ Return purchase price average """ + + if obj.purchase_price_avg: + # Get string representation of price average + purchase_price_avg = str(obj.purchase_price_avg) + else: + purchase_price_avg = '-' + + return purchase_price_avg + class Meta: model = BomItem fields = [ @@ -420,6 +454,7 @@ class BomItemSerializer(InvenTreeModelSerializer): 'purchase_price_min', 'purchase_price_max', 'purchase_price_avg', + 'purchase_price_range', ] diff --git a/InvenTree/templates/js/bom.js b/InvenTree/templates/js/bom.js index c97d8b30e5..e35a51d8bd 100644 --- a/InvenTree/templates/js/bom.js +++ b/InvenTree/templates/js/bom.js @@ -249,19 +249,6 @@ function loadBomTable(table, options) { title: '{% trans "Purchase Price Range" %}', searchable: false, sortable: true, - formatter: function(value, row, index, field) { - var purchase_price_range = 0; - - if (row.purchase_price_min > 0) { - if (row.purchase_price_min >= row.purchase_price_max) { - purchase_price_range = row.purchase_price_min; - } else { - purchase_price_range = row.purchase_price_min + " - " + row.purchase_price_max; - } - } - - return purchase_price_range; - }, }); cols.push( From 274eb51e48d7e8e4cea773b3223f33582791c869 Mon Sep 17 00:00:00 2001 From: eeintech Date: Fri, 14 May 2021 16:29:55 -0400 Subject: [PATCH 186/300] Added read_only args --- InvenTree/part/serializers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 868997915b..b6e24fd199 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -372,9 +372,9 @@ class BomItemSerializer(InvenTreeModelSerializer): purchase_price_max = MoneyField(max_digits=10, decimal_places=6, read_only=True) - purchase_price_avg = serializers.SerializerMethodField() + purchase_price_avg = serializers.SerializerMethodField(read_only=True) - purchase_price_range = serializers.SerializerMethodField() + purchase_price_range = serializers.SerializerMethodField(read_only=True) def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. From e9f41a83576f26b08e3f13b4c7e380184752b224 Mon Sep 17 00:00:00 2001 From: eeintech Date: Fri, 14 May 2021 16:38:30 -0400 Subject: [PATCH 187/300] Currency finding fix --- InvenTree/part/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 065eca30c6..5bdd572145 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -928,7 +928,7 @@ class BomList(generics.ListCreateAPIView): # Find associated currency (select first found) purchase_price_currency = None for currency_item in currencies: - if currency_item['pk'] == bom_item.pk and currency_item['sub_part'] == bom_item.sub_part: + if currency_item['pk'] == bom_item.pk and currency_item['sub_part'] == bom_item.sub_part.pk: purchase_price_currency = currency_item['purchase_price_currency'] break # Convert prices From 5ce262172d77d133ee591751adab63eb86fd663f Mon Sep 17 00:00:00 2001 From: eeintech Date: Fri, 14 May 2021 16:59:59 -0400 Subject: [PATCH 188/300] Fixed bom_item unit test --- InvenTree/part/serializers.py | 39 ++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index b6e24fd199..04e0b7a119 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -372,9 +372,9 @@ class BomItemSerializer(InvenTreeModelSerializer): purchase_price_max = MoneyField(max_digits=10, decimal_places=6, read_only=True) - purchase_price_avg = serializers.SerializerMethodField(read_only=True) + purchase_price_avg = serializers.SerializerMethodField() - purchase_price_range = serializers.SerializerMethodField(read_only=True) + purchase_price_range = serializers.SerializerMethodField() def __init__(self, *args, **kwargs): # part_detail and sub_part_detail serializers are only included if requested. @@ -406,19 +406,29 @@ class BomItemSerializer(InvenTreeModelSerializer): def get_purchase_price_range(self, obj): """ Return purchase price range """ - if obj.purchase_price_min and not obj.purchase_price_max: + try: + purchase_price_min = obj.purchase_price_min + except AttributeError: + return None + + try: + purchase_price_max = obj.purchase_price_max + except AttributeError: + return None + + if purchase_price_min and not purchase_price_max: # Get price range - purchase_price_range = str(obj.purchase_price_max) - elif not obj.purchase_price_min and obj.purchase_price_max: + purchase_price_range = str(purchase_price_max) + elif not purchase_price_min and purchase_price_max: # Get price range - purchase_price_range = str(obj.purchase_price_max) - elif obj.purchase_price_min and obj.purchase_price_max: + purchase_price_range = str(purchase_price_max) + elif purchase_price_min and purchase_price_max: # Get price range - if obj.purchase_price_min >= obj.purchase_price_max: + if purchase_price_min >= purchase_price_max: # If min > max: use min only - purchase_price_range = str(obj.purchase_price_min) + purchase_price_range = str(purchase_price_min) else: - purchase_price_range = str(obj.purchase_price_min) + " - " + str(obj.purchase_price_max) + purchase_price_range = str(purchase_price_min) + " - " + str(purchase_price_max) else: purchase_price_range = '-' @@ -427,9 +437,14 @@ class BomItemSerializer(InvenTreeModelSerializer): def get_purchase_price_avg(self, obj): """ Return purchase price average """ - if obj.purchase_price_avg: + try: + purchase_price_avg = obj.purchase_price_avg + except AttributeError: + return None + + if purchase_price_avg: # Get string representation of price average - purchase_price_avg = str(obj.purchase_price_avg) + purchase_price_avg = str(purchase_price_avg) else: purchase_price_avg = '-' From 6c30d128a1278f3f132060f3c9b40bd1c3da6587 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 May 2021 17:33:24 +0200 Subject: [PATCH 189/300] removing duplicate information --- InvenTree/part/templates/part/part_pricing.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index 9cadd1a655..e552d40024 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -4,11 +4,6 @@ {% load inventree_extras %} {% block pre_form_content %} -
    -{% blocktrans %}Pricing information for:
    {{part}}.{% endblocktrans %} -
    - -

    {% trans 'Quantity' %}

    From 16b7d6c34df29499653706b4ccea1f730fba0432 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 May 2021 18:18:58 +0200 Subject: [PATCH 190/300] database and debug info in version copy --- InvenTree/templates/version.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/InvenTree/templates/version.html b/InvenTree/templates/version.html index c8ec6862b6..3349bb5fb2 100644 --- a/InvenTree/templates/version.html +++ b/InvenTree/templates/version.html @@ -2,4 +2,6 @@ InvenTree-Version: {% inventree_version %} Django Version: {% django_version %} {% inventree_commit_hash as hash %}{% if hash %}Commit Hash: {{ hash }}{% endif %} -{% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {{ commit_date }}{% endif %} \ No newline at end of file +{% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {{ commit_date }}{% endif %} +Database: {% inventree_db_engine %} +Debug-Mode: {% inventree_in_debug_mode %} From b2a912c77020786048f5b0ed11acb0eca8f4cc03 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 May 2021 18:19:35 +0200 Subject: [PATCH 191/300] docker-mode switch in settings and tags --- InvenTree/InvenTree/settings.py | 5 +++++ InvenTree/part/templatetags/inventree_extras.py | 7 +++++++ docker/Dockerfile | 1 + 3 files changed, 13 insertions(+) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 7ff90fc7c3..67a500a07a 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -87,6 +87,11 @@ DEBUG = _is_true(get_setting( CONFIG.get('debug', True) )) +DOCKER = _is_true(get_setting( + 'INVENTREE_DOCKER', + False +)) + # Configure logging settings log_level = get_setting( 'INVENTREE_LOG_LEVEL', diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index e8743028a0..734b365447 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -81,6 +81,13 @@ def inventree_in_debug_mode(*args, **kwargs): return djangosettings.DEBUG +@register.simple_tag() +def inventree_docker_mode(*args, **kwargs): + """ Return True if the server is running as a Docker image """ + + return djangosettings.DOCKER + + @register.simple_tag() def inventree_db_engine(*args, **kwargs): """ Return the InvenTree database backend e.g. 'postgresql' """ diff --git a/docker/Dockerfile b/docker/Dockerfile index 3e0a7e1230..ea70d9f994 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -14,6 +14,7 @@ ENV INVENTREE_REPO="${repository}" ENV INVENTREE_BRANCH="${branch}" ENV INVENTREE_LOG_LEVEL="INFO" +ENV INVENTREE_DOCKER="true" # InvenTree paths ENV INVENTREE_SRC_DIR="${INVENTREE_HOME}/src" From ff9970f1cc42a823be665a6e9d1baa7437fcc22a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 May 2021 18:20:06 +0200 Subject: [PATCH 192/300] docker in version copy --- InvenTree/templates/version.html | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/templates/version.html b/InvenTree/templates/version.html index 3349bb5fb2..b702fd85f5 100644 --- a/InvenTree/templates/version.html +++ b/InvenTree/templates/version.html @@ -5,3 +5,4 @@ Django Version: {% django_version %} {% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {{ commit_date }}{% endif %} Database: {% inventree_db_engine %} Debug-Mode: {% inventree_in_debug_mode %} +Deployed using Docker: {% inventree_docker_mode %} \ No newline at end of file From cfa6994302ec85494cdbf8b90313ccd9ecbb5b0c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 16 May 2021 18:20:32 +0200 Subject: [PATCH 193/300] docker-mode in stats --- InvenTree/templates/stats.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/InvenTree/templates/stats.html b/InvenTree/templates/stats.html index 1598d45d26..403030644a 100644 --- a/InvenTree/templates/stats.html +++ b/InvenTree/templates/stats.html @@ -26,6 +26,14 @@ {% endif %} + {% inventree_docker_mode as docker_mode %} + {% if docker_mode %} + + + + + + {% endif %} {% if user.is_staff %} From 64c1503fe4a75761c1cc41fce94d409c411f451a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 17 May 2021 20:15:53 +1000 Subject: [PATCH 194/300] Disable "purchase price" field for non-purchaseable parts --- InvenTree/templates/js/modals.js | 9 +++++++++ InvenTree/templates/js/stock.js | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/InvenTree/templates/js/modals.js b/InvenTree/templates/js/modals.js index b621caab80..f447fdce72 100644 --- a/InvenTree/templates/js/modals.js +++ b/InvenTree/templates/js/modals.js @@ -89,6 +89,15 @@ function setFieldOptions(fieldName, optionList, options={}) { } +function clearFieldOptions(fieldName) { + /** + * Clear (emtpy) the options list for a particular field + */ + + setFieldOptions(fieldName, []); +} + + function reloadFieldOptions(fieldName, options) { /* Reload the options for a given field, * using an AJAX request. diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index a0601aeb13..8f06d403ee 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -1218,6 +1218,17 @@ function createNewStockItem(options) { field: 'part', action: function(value) { + if (!value) { + // No part chosen + + clearFieldOptions('supplier_part'); + enableField('serial_numbers', false); + enableField('purchase_price_0', false); + enableField('purchase_price_1', false); + + return; + } + // Reload options for supplier part reloadFieldOptions( 'supplier_part', @@ -1243,6 +1254,9 @@ function createNewStockItem(options) { enableField('serial_numbers', response.trackable); clearField('serial_numbers'); + enableField('purchase_price_0', response.purchaseable); + enableField('purchase_price_1', response.purchaseable); + // Populate the expiry date if (response.default_expiry <= 0) { // No expiry date From 52045676281f6ff306620ecdf340ba4d5d8c3324 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 19:06:41 +1000 Subject: [PATCH 195/300] Bug fix for stock item tracking API --- InvenTree/stock/api.py | 3 +++ InvenTree/templates/js/stock.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 376d04f643..3fc440cae4 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -1018,6 +1018,9 @@ class StockTrackingList(generics.ListAPIView): for item in data: deltas = item['deltas'] + if not deltas: + deltas = {} + # Add location detail if 'location' in deltas: try: diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 8f06d403ee..b89cceea83 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -1017,6 +1017,11 @@ function loadStockTrackingTable(table, options) { formatter: function(details, row, index, field) { var html = `
    {% trans 'Part' %}{% trans "Server is running in debug mode" %}
    {% trans "Docker Mode" %}{% trans "Server is deployed using docker" %}
    `; + if (!details) { + html += '
    '; + return html; + } + // Location information if (details.location) { From a1c4662e9148eec05d24ea9c1317430f7a8035bb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 19:11:37 +1000 Subject: [PATCH 196/300] Move status messages for stock item --- InvenTree/InvenTree/static/css/inventree.css | 8 ++ .../stock/templates/stock/item_base.html | 129 +++++++++--------- InvenTree/templates/two_column.html | 2 + 3 files changed, 77 insertions(+), 62 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index e3191405d9..5271a9b362 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -901,6 +901,14 @@ input[type="submit"] { color: #e00; } +.info-messages { + padding: 5px; +} + +.info-messages .alert { + padding: 5px; +} + .part-allocation { padding: 3px 10px; border: 1px solid #ccc; diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index 54d6b12e4f..da770bab48 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -14,68 +14,6 @@ {% block pre_content %} {% include 'stock/loc_link.html' with location=item.location %} - -{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} -{% if owner_control.value == "True" %} - {% authorized_owners item.owner as owners %} - - {% if not user in owners and not user.is_superuser %} -
    - {% trans "You are not in the list of owners of this item. This stock item cannot be edited." %}
    -
    - {% endif %} -{% endif %} - -{% if item.is_building %} -
    - {% trans "This stock item is in production and cannot be edited." %}
    - {% trans "Edit the stock item from the build view." %}
    - - {% if item.build %} - - {{ item.build }} - - {% endif %} - -
    -{% endif %} - -{% if item.hasRequiredTests and not item.passedAllRequiredTests %} -
    - {% trans "This stock item has not passed all required tests" %} -
    -{% endif %} - -{% for allocation in item.sales_order_allocations.all %} -
    - {% object_link 'so-detail' allocation.line.order.id allocation.line.order as link %} - {% decimal allocation.quantity as qty %} - {% blocktrans %}This stock item is allocated to Sales Order {{ link }} (Quantity: {{ qty }}){% endblocktrans %} -
    -{% endfor %} - -{% for allocation in item.allocations.all %} -
    - {% object_link 'build-detail' allocation.build.id allocation.build %} - {% decimal allocation.quantity as qty %} - {% blocktrans %}This stock item is allocated to Build {{ link }} (Quantity: {{ qty }}){% endblocktrans %} -
    -{% endfor %} - -{% if item.serialized %} -
    - {% trans "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." %} -
    -{% elif item.child_count > 0 %} -
    - {% trans "This stock item cannot be deleted as it has child items" %} -
    -{% elif item.delete_on_deplete and item.can_delete %} -
    - {% trans "This stock item will be automatically deleted when all stock is depleted." %} -
    -{% endif %} - {% endblock %} {% block thumbnail %} @@ -221,6 +159,73 @@ {% endblock %} +{% block below_thumbnail %} +
    + + {% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} + {% if owner_control.value == "True" %} + {% authorized_owners item.owner as owners %} + + {% if not user in owners and not user.is_superuser %} +
    + {% trans "You are not in the list of owners of this item. This stock item cannot be edited." %}
    +
    + {% endif %} + {% endif %} + + {% if item.is_building %} +
    + {% trans "This stock item is in production and cannot be edited." %}
    + {% trans "Edit the stock item from the build view." %}
    + + {% if item.build %} + + {{ item.build }} + + {% endif %} + +
    + {% endif %} + + {% if item.hasRequiredTests and not item.passedAllRequiredTests %} +
    + {% trans "This stock item has not passed all required tests" %} +
    + {% endif %} + + {% for allocation in item.sales_order_allocations.all %} +
    + {% object_link 'so-detail' allocation.line.order.id allocation.line.order as link %} + {% decimal allocation.quantity as qty %} + {% blocktrans %}This stock item is allocated to Sales Order {{ link }} (Quantity: {{ qty }}){% endblocktrans %} +
    + {% endfor %} + + {% for allocation in item.allocations.all %} +
    + {% object_link 'build-detail' allocation.build.id allocation.build %} + {% decimal allocation.quantity as qty %} + {% blocktrans %}This stock item is allocated to Build {{ link }} (Quantity: {{ qty }}){% endblocktrans %} +
    + {% endfor %} + + {% if item.serialized %} +
    + {% trans "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." %} +
    + {% elif item.child_count > 0 %} +
    + {% trans "This stock item cannot be deleted as it has child items" %} +
    + {% elif item.delete_on_deplete and item.can_delete %} +
    + {% trans "This stock item will be automatically deleted when all stock is depleted." %} +
    + {% endif %} + +
    +{% endblock %} + {% block page_details %}

    {% trans "Stock Item Details" %}

    diff --git a/InvenTree/templates/two_column.html b/InvenTree/templates/two_column.html index ce91dcfffb..1eb1b5388e 100644 --- a/InvenTree/templates/two_column.html +++ b/InvenTree/templates/two_column.html @@ -27,6 +27,8 @@ {% endblock %} + {% block below_thumbnail %} + {% endblock %}
    {% block page_details %} From 7cd345aeb570dead59f7c330be38c758ec7ed95b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 19:19:43 +1000 Subject: [PATCH 197/300] Change location of 'banner' messages - Place them inside the main panel - Generally underneath the thumbnail --- InvenTree/InvenTree/static/css/inventree.css | 1 + .../build/templates/build/build_base.html | 78 +++++++++++-------- .../templates/order/sales_order_base.html | 14 ++-- InvenTree/part/templates/part/part_base.html | 16 ++-- 4 files changed, 62 insertions(+), 47 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 5271a9b362..0aab04f941 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -907,6 +907,7 @@ input[type="submit"] { .info-messages .alert { padding: 5px; + margin-bottom: 10px; } .part-allocation { diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index 177fad8d6c..2376daf0cf 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -9,44 +9,54 @@ {% inventree_title %} | {% trans "Build Order" %} - {{ build }} {% endblock %} +{% block below_thumbnail %} + +
    + {% if build.sales_order %} +
    + {% object_link 'so-detail' build.sales_order.id build.sales_order as link %} + {% blocktrans %}This Build Order is allocated to Sales Order {{link}}{% endblocktrans %} +
    + {% endif %} + + {% if build.parent %} +
    + {% object_link 'build-detail' build.parent.id build.parent as link %} + {% blocktrans %}This Build Order is a child of Build Order {{link}}{% endblocktrans %} +
    + {% endif %} + + {% if build.active %} + {% if build.can_complete %} +
    + {% trans "Build Order is ready to mark as completed" %} +
    + {% endif %} + {% if build.incomplete_count > 0 %} +
    + {% trans "Build Order cannot be completed as outstanding outputs remain" %} +
    + {% endif %} + {% if build.completed < build.quantity %} +
    + {% trans "Required build quantity has not yet been completed" %} +
    + {% endif %} + {% if not build.areUntrackedPartsFullyAllocated %} +
    + {% trans "Stock has not been fully allocated to this Build Order" %} +
    + {% endif %} + {% endif %} +
    +{% endblock %} + {% block header_pre_content %} -{% if build.sales_order %} -
    - {% object_link 'so-detail' build.sales_order.id build.sales_order as link %} - {% blocktrans %}This Build Order is allocated to Sales Order {{link}}{% endblocktrans %} -
    -{% endif %} -{% if build.parent %} -
    - {% object_link 'build-detail' build.parent.id build.parent as link %} - {% blocktrans %}This Build Order is a child of Build Order {{link}}{% endblocktrans %} -
    -{% endif %} + {% endblock %} {% block header_post_content %} -{% if build.active %} -{% if build.can_complete %} -
    - {% trans "Build Order is ready to mark as completed" %} -
    -{% endif %} -{% if build.incomplete_count > 0 %} -
    - {% trans "Build Order cannot be completed as outstanding outputs remain" %} -
    -{% endif %} -{% if build.completed < build.quantity %} -
    - {% trans "Required build quantity has not yet been completed" %} -
    -{% endif %} -{% if not build.areUntrackedPartsFullyAllocated %} -
    - {% trans "Stock has not been fully allocated to this Build Order" %} -
    -{% endif %} -{% endif %} + {% endblock %} {% block thumbnail %} diff --git a/InvenTree/order/templates/order/sales_order_base.html b/InvenTree/order/templates/order/sales_order_base.html index 45bcc76244..d3f4ba74a2 100644 --- a/InvenTree/order/templates/order/sales_order_base.html +++ b/InvenTree/order/templates/order/sales_order_base.html @@ -9,13 +9,15 @@ {% inventree_title %} | {% trans "Sales Order" %} {% endblock %} -{% block pre_content %} -{% if order.status == SalesOrderStatus.PENDING and not order.is_fully_allocated %} -
    - {% trans "This SalesOrder has not been fully allocated" %} +{% block below_thumbnail %} +
    + {% if order.status == SalesOrderStatus.PENDING and not order.is_fully_allocated %} +
    + {% trans "This Sales Order has not been fully allocated" %} +
    + {% endif %}
    -{% endif %} -{% endblock %} + {% endblock %} {% block thumbnail %} -{% if part.variant_of %} -
    - {% object_link 'part-variants' part.variant_of.id part.variant_of.full_name as link %} - {% blocktrans %}This part is a variant of {{link}}{% endblocktrans %} -
    -{% endif %} -
    {% include "part/part_thumb.html" %} @@ -107,6 +100,15 @@
    + +
    + {% if part.variant_of %} +
    + {% object_link 'part-variants' part.variant_of.id part.variant_of.full_name as link %} + {% blocktrans %}This part is a variant of {{link}}{% endblocktrans %} +
    + {% endif %} +
    From 013d42de7ade2fe5e405f5c3a29511c3f08e9760 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 18 May 2021 19:20:24 +1000 Subject: [PATCH 198/300] L10 merge (#1595) * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * Adds a commit message * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * New Crowdin updates (#1551) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * New Crowdin updates (#1552) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * New Crowdin updates (#1568) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * New Crowdin updates (#1570) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- InvenTree/locale/de/LC_MESSAGES/django.po | 1946 +++++++++------- InvenTree/locale/en/LC_MESSAGES/django.po | 1781 +++++++------- InvenTree/locale/es/LC_MESSAGES/django.po | 1923 ++++++++------- InvenTree/locale/fr/LC_MESSAGES/django.po | 1823 ++++++++------- InvenTree/locale/it/LC_MESSAGES/django.po | 1797 +++++++------- InvenTree/locale/ja/LC_MESSAGES/django.po | 1797 +++++++------- InvenTree/locale/pl/LC_MESSAGES/django.po | 2581 +++++++++++---------- InvenTree/locale/ru/LC_MESSAGES/django.po | 1797 +++++++------- InvenTree/locale/tr/LC_MESSAGES/django.po | 1931 ++++++++------- InvenTree/locale/zh/LC_MESSAGES/django.po | 1837 ++++++++------- crowdin.yml | 3 + 11 files changed, 10665 insertions(+), 8551 deletions(-) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index d8342de36c..300a639a69 100644 --- a/InvenTree/locale/de/LC_MESSAGES/django.po +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 10:02\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: German\n" "Language: de_DE\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: de\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -72,8 +77,8 @@ msgstr "Kategorie auswählen" msgid "Duplicate serial: {n}" msgstr "Doppelte Seriennummer: {n}" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "Keine gültige Menge" @@ -101,7 +106,7 @@ msgstr "Keine Seriennummern gefunden" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "Anzahl der eindeutigen Seriennummern ({s}) muss mit der Anzahl ({q}) übereinstimmen" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "Anhang" @@ -117,9 +122,9 @@ msgstr "Kommentar" msgid "File comment" msgstr "Datei-Kommentar" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "Benutzer" @@ -127,8 +132,8 @@ msgstr "Benutzer" msgid "upload date" msgstr "Hochladedatum" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -136,11 +141,11 @@ msgid "Name" msgstr "Name" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,7 +159,7 @@ msgstr "Name" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "Beschreibung" @@ -166,23 +171,23 @@ msgstr "Beschreibung (optional)" msgid "parent" msgstr "Eltern" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "Englisch" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "Französisch" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "Deutsch" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "Polnisch" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "Türkisch" @@ -198,60 +203,136 @@ msgstr "E-Mail-Backend nicht konfiguriert" msgid "InvenTree system health checks failed" msgstr "InvenTree Status-Überprüfung fehlgeschlagen" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "Ausstehend" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "Platziert" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "Fertig" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "Storniert" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "Verloren" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "Zurückgegeben" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "Versendet" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "OK" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "erfordert Eingriff" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "Beschädigt" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "Zerstört" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "Zurückgewiesen" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "Alter Lagerbestands-Tracking-Eintrag" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "Lagerbestand erstellt" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "Lagerbestand bearbeitet" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "Seriennummer hinzugefügt" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "Lagerbestand gezählt" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "Lagerbestand manuell hinzugefügt" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "Lagerbestand manuell entfernt" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "Standort geändert" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "In Baugruppe installiert" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "Aus Baugruppe entfernt" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "Komponente installiert" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "Komponente entfernt" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "Vom übergeordneten Element geteilt" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "Unterobjekt geteilt" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "Zum Kunden geschickt" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "Rücksendung vom Kunden" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "Endprodukt erstellt" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "Endprodukt fertiggestellt" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "Gegen Bestellung empfangen" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "in Arbeit" @@ -270,8 +351,9 @@ msgstr "IPN muss zu Regex-Muster {pat} passen" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" -msgstr "Referenz muss zu Regex-Muster passen" +#, python-brace-format +msgid "Reference must match pattern {pattern}" +msgstr "Referenz muss zu Regex-Muster {pattern} passen" #: InvenTree/validators.py:113 #, python-brace-format @@ -376,35 +458,35 @@ msgstr "Zieldatum" msgid "Target date for build completion. Build will be overdue after this date." msgstr "Zieldatum für Bauauftrag-Fertigstellung." -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "Anzahl" @@ -416,7 +498,7 @@ msgstr "Anzahl der zu bauenden Teile" msgid "Enter quantity for build output" msgstr "Menge der Endprodukte angeben" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "Seriennummer" @@ -446,11 +528,11 @@ msgstr "Bauauftrag als vollständig markieren" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "Lagerort" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "Lagerort der Endprodukte" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "Status" @@ -517,9 +600,9 @@ msgstr "Bauaufträge" msgid "Build Order Reference" msgstr "Bauauftragsreferenz" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "Bauauftrag, zu dem dieser Bauauftrag zugwiesen ist" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "Bauauftrag, zu dem dieser Bauauftrag zugwiesen ist" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "Teil" @@ -616,7 +699,7 @@ msgstr "Bauauftrags-Status" msgid "Build status code" msgstr "Bau-Statuscode" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "Losnummer" @@ -629,7 +712,7 @@ msgstr "Losnummer für dieses Endprodukt" msgid "Creation Date" msgstr "Erstelldatum" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "geplantes Fertigstellungsdatum" @@ -667,28 +750,28 @@ msgstr "Nutzer der für diesen Bauauftrag zuständig ist" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "Externer Link" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "Link zu einer externen URL" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "Endprodukt bereits hergstellt" msgid "Build output does not match Build Order" msgstr "Endprodukt stimmt nicht mit dem Bauauftrag überein" -#: build/models.py:838 -msgid "Completed build output" -msgstr "Endprodukt fertigstellen" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "Bauauftrags-Objekt muss für Bauauftrag, Lager-Objekt und installiert_in eindeutig sein" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 +msgid "Build item must specify a build output, as master part is marked as trackable" +msgstr "Bauauftragsposition muss ein Endprodukt festlegen, da der übergeordnete Teil verfolgbar ist" + +#: build/models.py:1165 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "Ausgewähltes BestandsObjekt nicht Stückliste für Teil '{p}' gefunden" -#: build/models.py:1165 +#: build/models.py:1169 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "Reserviermenge ({n}) muss kleiner Bestandsmenge ({q}) sein. Zugewiesene Anzahl ({n}) darf nicht die verfügbare ({q}) Anzahl überschreiten" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "Zu viele BestandsObjekt zugewiesen" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "Reserviermenge muss größer null sein" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "Anzahl muss 1 für Objekte mit Seriennummer sein" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "Bauauftrag" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "Bauauftrag starten um Teile zuzuweisen" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "BestandsObjekt" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "Quell-BestandsObjekt" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "BestandsObjekt-Anzahl dem Bauauftrag zuweisen" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "Installiere in" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "Ziel-BestandsObjekt" @@ -812,29 +891,29 @@ msgstr "Benötigte Teile bestellen" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "Teile bestellen" #: build/templates/build/allocate.html:36 msgid "Untracked stock has been fully allocated for this Build Order" -msgstr "" +msgstr "Nicht verfolgter Lagerbestand wurde Bauauftrag vollständig zugewiesen" #: build/templates/build/allocate.html:40 msgid "Untracked stock has not been fully allocated for this Build Order" -msgstr "" +msgstr "Nicht verfolgter Lagerbestand wurde Bauauftrag noch nicht vollständig zugewiesen" #: build/templates/build/allocate.html:47 msgid "This Build Order does not have any associated untracked BOM items" -msgstr "" +msgstr "Dieser Bauauftrag hat keine zugeordneten Stücklisten-Einträge" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "Seriennummer" @@ -897,7 +976,7 @@ msgstr "Lagerbestand wurde Bauauftrag noch nicht vollständig zugewiesen" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "Admin" @@ -908,8 +987,8 @@ msgstr "Admin" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "Überfällig" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "Fortschritt" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "Auftrag" @@ -974,7 +1053,7 @@ msgstr "Aufgegeben von" #: build/templates/build/build_base.html:207 msgid "Incomplete Outputs" -msgstr "Unvollständige Endprodukte" +msgstr "Unfertige Endprodukte" #: build/templates/build/build_base.html:208 msgid "Build Order cannot be completed as incomplete build outputs remain" @@ -1112,11 +1191,11 @@ msgid "Destination location not specified" msgstr "Ziel-Lagerort nicht angegeben" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" -msgstr "Los" +msgstr "Losnummer" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 @@ -1168,6 +1247,7 @@ msgstr "Bauauftrag-details" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "Details" @@ -1202,7 +1282,8 @@ msgstr "Bermerkungen bearbeiten" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "Speichern" @@ -1229,9 +1310,9 @@ msgstr "Endprodukt anlegen" #: build/views.py:168 msgid "Maximum output quantity is " -msgstr "" +msgstr "Maximale Endproduktmenge ist " -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "Seriennummern existieren bereits" @@ -1348,372 +1429,405 @@ msgstr "Bauobjekt aktualisiert" msgid "Add Build Order Attachment" msgstr "Bauauftrags-Anhang hinzufügen" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "Anhang hinzugefügt" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "Anhang bearbeiten" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "Anhang aktualisiert" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "Anhang löschen" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "Anhang gelöscht" -#: common/models.py:56 +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "Dateiformat nicht unterstützt: {ext.upper()}" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "Fehler beim Lesen der Datei (ungültiges Format)" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "Fehler beim Lesen der Datei (falsche Größe)" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "Fehler beim Lesen der Datei (Daten könnten beschädigt sein)" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "Datei" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "Datei zum Hochladen auswählen" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "{name.title()} Datei" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" +msgstr "{name} Datei zum Hochladen auswählen" + +#: common/models.py:58 msgid "InvenTree Instance Name" msgstr "InvenTree Instanzname" -#: common/models.py:58 +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "Kurze Beschreibung der Instanz" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "Name der Instanz verwenden" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "Den Namen der Instanz in der Titelleiste verwenden" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "Firmenname" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "interner Firmenname" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "Basis-URL" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "Basis-URL für dieses Instanz" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "Standard-Währung" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "Standard-Währung" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "Von URL herunterladen" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "Herunterladen von externen Bildern und Dateien von URLs erlaubt" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "Bacode-Feature verwenden" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "Barcode-Scanner Unterstützung" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "IPN Regex" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "RegEx Muster für die Zuordnung von Teil-IPN" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "Mehrere Artikel mit gleicher IPN erlaubt" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "Mehrere Artikel mit gleicher IPN erlaubt" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "Ändern von IPN erlaubt" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "Ändern der IPN während des Bearbeiten eines Teils erlaubt" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "Teil-Stückliste kopieren" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "Stückliste von Teil kopieren wenn das Teil dupliziert wird " -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "Teil-Parameter kopieren" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "Parameter-Daten für dieses Teil kopieren wenn das Teil dupliziert wird" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "Teil-Testdaten kopieren" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "Test-Daten für dieses Teil kopieren wenn das Teil dupliziert wird" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "Kategorie-Parametervorlage kopieren" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "Kategorie-Parameter Vorlagen kopieren wenn ein Teil angelegt wird" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "Aktuelle Teile-Stände" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "Anzahl der neusten Teile auf der Startseite" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "Vorlage" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "Teile sind standardmäßig Vorlagen" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "Baugruppe" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "Teile können standardmäßig aus anderen Teilen angefertigt werden" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "Komponente" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "Teile können standardmäßig in Baugruppen benutzt werden" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "Kaufbar" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "Artikel sind grundsätzlich kaufbar" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "Verkäuflich" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "Artikel sind grundsätzlich verkaufbar" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" -msgstr "nachverfolgbar" +msgstr "Nachverfolgbar" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "Artikel sind grundsätzlich verfolgbar" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "Virtuell" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "Teile sind grundsätzlich virtuell" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "zeige Bestand in Eingabemasken" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "Zeige den verfügbaren Bestand in einigen Eingabemasken" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "Entwickler-Modus" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "Berichte im Entwickler-Modus generieren (als HTML)" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "Seitengröße" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "Standardseitenformat für PDF-Bericht" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "Test-Berichte" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "Erstellung von Test-Berichten aktivieren" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "Bestands-Ablauf" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "Ablaufen von Bestand ermöglichen" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "Abgelaufenen Bestand verkaufen" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "Verkauf von abgelaufenem Bestand erlaubt" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "Bestands-Stehzeit" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "Anzahl an Tagen, an denen Bestand als abgestanden markiert wird, bevor sie ablaufen" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "Tage" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "Abgelaufenen Bestand verbauen" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "Verbauen von abgelaufenen Bestand erlaubt" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "Bestands-Eigentümerkontrolle" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "Eigentümerkontrolle für Lagerorte und Teile aktivieren" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "Gruppieren nach Teil" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "Bestand in Tabellen anhand von Teil-Referenz gruppieren" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "aktueller Bestand" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "Anzahl des geänderten Bestands auf der Startseite" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "Bauauftrag-Referenz Präfix" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "Präfix für Bauauftrag-Referenz" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "Bauauftrag-Referenz RegEx" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "RegEx Muster für die Zuordnung von Bauauftrag-Referenzen" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "Auftrags-Referenz Präfix" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "Präfix für Auftrags-Referenz" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "Bestellungs-Referenz Präfix" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "Präfix für Bestellungs-Referenz" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "Einstellungs-Schlüssel (muss einzigartig sein, Groß-/ Kleinschreibung wird nicht beachtet)" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "Einstellungs-Wert" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "Nur Ganzzahl eingeben" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "Wahrheitswert erforderlich" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "Nur Ganzzahl eingeben" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "Schlüsseltext muss eindeutig sein" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "Preisstaffelungs Anzahl" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "Preis" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "Stückpreis für die angegebene Anzahl" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "Standard" @@ -1721,24 +1835,42 @@ msgstr "Standard" msgid "Current value" msgstr "Aktueller Wert" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "Einstellungen ändern" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "Angegebener Wert nicht erlaubt" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "Angegebener Wert muss ein Wahrheitswert sein" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "Datei hochgeladen" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "Übereinstimmende Felder" + +#: common/views.py:186 +msgid "Match Items" +msgstr "Positionen zuordnen" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "Felder zuteilen fehlgeschlagen" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "Währung" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "Standard-Währung für diese Firma" @@ -1758,216 +1890,216 @@ msgstr "Einzelpreis" msgid "Single quantity price" msgstr "Preis für eine Einheit" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "Hersteller auswählen" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "Hersteller-Teilenummer" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "MPN" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "Firmenbeschreibung" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "Firmenbeschreibung" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "Website" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "Firmenwebsite Adresse/URL" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "Adresse" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "Firmenadresse" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "Kontakt-Tel." -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "Kontakt-Telefon" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "Email" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "Kontakt-Email" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "Kontakt" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "Anlaufstelle" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "Link" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "Link auf externe Firmeninformation" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "Bild" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "ist Kunde" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "Verkaufen Sie Teile an diese Firma?" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "ist Zulieferer" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "Kaufen Sie Teile von dieser Firma?" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "ist Hersteller" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "Produziert diese Firma Teile?" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "Basisteil" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "Teil auswählen" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "Hersteller" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "Externe URL für das Herstellerteil" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "Teilbeschreibung des Herstellers" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "Zulieferer" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "Zulieferer auswählen" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "SKU (Lagerbestandseinheit)" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "Lagerbestandseinheit (SKU) des Zulieferers" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" -msgstr "Hersteller-Teil" +msgstr "Herstellerteil" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "Herstellerteil auswählen" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "Teil-URL des Zulieferers" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "Zuliefererbeschreibung des Teils" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "Notiz" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "Basiskosten" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "Mindestpreis" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "Verpackungen" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "Teile-Verpackungen" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "Vielfache" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "Mehrere bestellen" @@ -1993,7 +2125,7 @@ msgstr "Neues Bild hochladen" msgid "Download image from URL" msgstr "Bild von URL herunterladen" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "Bestellung anlegen" @@ -2022,11 +2154,9 @@ msgstr "Sind Sie sicher, dass Sie die Firma '%(name)s' löschen wollen?" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." -msgstr "" -"Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
    \n" +msgstr "Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
    \n" "Wenn dieser Lieferant gelöscht wird, werden auch diese Zulieferer-Teile gelöscht." #: company/templates/company/detail.html:21 @@ -2041,10 +2171,11 @@ msgstr "Keine Website angegeben" msgid "Uses default currency" msgstr "verwendet Standard-Währung" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "Kunde" @@ -2090,7 +2221,7 @@ msgstr "Teile löschen" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "Neues Teil" @@ -2126,30 +2257,30 @@ msgstr "Exportieren" #: company/templates/company/manufacturer_part_suppliers.html:10 #: templates/InvenTree/search.html:164 msgid "Supplier Parts" -msgstr "Zulieferer-Teile" +msgstr "Zuliefererteile" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 #: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" -msgstr "Neues Zulieferer-Teil anlegen" +msgstr "Neues Zuliefererteil anlegen" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" -msgstr "Neues Zulieferer-Teil" +msgstr "Neues Zuliefererteil" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "Neuer Zulieferer" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "Neuen Zulieferer anlegen" @@ -2207,7 +2338,7 @@ msgstr "Herstellerteil-Bestand" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2251,7 +2382,7 @@ msgstr "Hergestellte Teile" #: company/templates/company/navbar.html:29 #: company/templates/company/navbar.html:32 msgid "Supplied Parts" -msgstr "Zulieferer-Teile" +msgstr "Zuliefererteile" #: company/templates/company/navbar.html:38 part/templates/part/navbar.html:33 #: stock/templates/stock/location.html:107 @@ -2260,9 +2391,9 @@ msgstr "Zulieferer-Teile" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" -msgstr "BestandsObjekte" +msgstr "Teilbestand" #: company/templates/company/navbar.html:47 #: company/templates/company/navbar.html:56 @@ -2315,27 +2446,27 @@ msgid "New Sales Order" msgstr "Neuer Auftrag" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" -msgstr "Zulieferer-Teil" +msgstr "Zuliefererteil" #: company/templates/company/supplier_part_base.html:40 msgid "Edit supplier part" -msgstr "Zulieferer-Teil bearbeiten" +msgstr "Zuliefererteil bearbeiten" #: company/templates/company/supplier_part_base.html:44 msgid "Delete supplier part" -msgstr "Zulieferer-Teil entfernen" +msgstr "Zuliefererteil entfernen" #: company/templates/company/supplier_part_base.html:56 #: company/templates/company/supplier_part_detail.html:10 msgid "Supplier Part Details" -msgstr "Zulieferer-Teildetails" +msgstr "Zuliefererteil Details" #: company/templates/company/supplier_part_delete.html:5 msgid "Are you sure you want to delete the following Supplier Parts?" -msgstr "Sind Sie sicher, dass sie die folgenden Zulieferer-Teile löschen möchten?" +msgstr "Sind Sie sicher, dass sie die folgenden Zuliefererteile löschen möchten?" #: company/templates/company/supplier_part_navbar.html:12 #: company/templates/company/supplier_part_stock.html:10 @@ -2349,7 +2480,7 @@ msgstr "Zulieferer-Bestellungen" #: company/templates/company/supplier_part_navbar.html:26 msgid "Supplier Part Pricing" -msgstr "Zulieferer-Teil Bepreisung" +msgstr "Zuliefererteil Bepreisung" #: company/templates/company/supplier_part_navbar.html:29 msgid "Pricing" @@ -2365,7 +2496,7 @@ msgid "Pricing Information" msgstr "Preisinformationen ansehen" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "Preisstaffel hinzufügen" @@ -2395,7 +2526,7 @@ msgstr "Hersteller" msgid "Customers" msgstr "Kunden" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "Neuer Kunde" @@ -2415,6 +2546,11 @@ msgstr "Bild herunterladen" msgid "Image size exceeds maximum allowable size for download" msgstr "Bildgröße überschreitet maximal-erlaubte Größe für Downloads" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "Ungültige Antwort {code}" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "Angegebene URL ist kein gültiges Bild" @@ -2435,7 +2571,7 @@ msgstr "Firma bearbeiten" msgid "Edited company information" msgstr "Firmeninformation bearbeitet" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "Neuen Kunden anlegen" @@ -2453,7 +2589,7 @@ msgstr "Firma gelöscht" #: company/views.py:357 msgid "Edit Manufacturer Part" -msgstr "Hergestellte Teile ändern" +msgstr "Herstellerteil ändern" #: company/views.py:366 msgid "Create New Manufacturer Part" @@ -2465,25 +2601,25 @@ msgstr "Herstellerteil löschen" #: company/views.py:528 msgid "Edit Supplier Part" -msgstr "Zulieferer-Teil bearbeiten" +msgstr "Zuliefererteil bearbeiten" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" -msgstr "Neues Zulieferer-Teil anlegen" +msgstr "Neues Zuliefererteil anlegen" #: company/views.py:722 msgid "Delete Supplier Part" -msgstr "Zulieferer-Teil entfernen" +msgstr "Zuliefererteil entfernen" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "neue Preisstaffel hinzufügt" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "Preisstaffel bearbeiten" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "Preisstaffel löschen" @@ -2491,51 +2627,59 @@ msgstr "Preisstaffel löschen" msgid "No valid objects provided to template" msgstr "Keine korrekten Objekte für Vorlage gegeben" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "Label Name" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "Label Beschreibung" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "Label" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "Label-Vorlage-Datei" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "Aktiviert" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "Label-Vorlage ist aktiviert" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "Breite [mm]" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "Label-Breite in mm" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "Höhe [mm]" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "Label-Höhe in mm" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "Dateinamen-Muster" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "Muster für die Erstellung von Label-Dateinamen" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "Abfragefilter (kommagetrennte Liste mit Schlüssel=Wert-Paaren)" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "Filter" @@ -2573,15 +2717,15 @@ msgstr "Zieldatum für Auftrags-Lieferung." msgid "Enter sales order number" msgstr "Auftrag-Nummer eingeben" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "Zieldatum für Auftrags-Fertigstellung." -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "Seriennummern für BestandsObjekt eingeben" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "Menge der BestandsObjekt eingeben" @@ -2609,7 +2753,7 @@ msgstr "Nutzer oder Gruppe der/die für diesen Auftrag zuständig ist/sind" msgid "Order notes" msgstr "Bestell-Notizen" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "Bestellungs-Status" @@ -2650,8 +2794,8 @@ msgstr "Geplantes Lieferdatum für Auftrag." msgid "Date order was completed" msgstr "Datum an dem der Auftrag fertigstellt wurde" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -2659,132 +2803,134 @@ msgstr "Anzahl muss größer Null sein" msgid "Part supplier must match PO supplier" msgstr "Teile-Zulieferer muss dem Zulieferer der Bestellung entsprechen" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "Nur Teile aufgegebener Bestllungen können empfangen werden" -#: order/models.py:348 -#, fuzzy -#| msgid "Quantity must be integer" +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "Anzahl muss eine Ganzzahl sein" -#: order/models.py:350 -#, fuzzy -#| msgid "Quantity must be positive" +#: order/models.py:352 msgid "Quantity must be a positive number" -msgstr "Anzahl muss positiv sein" +msgstr "Anzahl muss eine positive Zahl sein" -#: order/models.py:369 -msgid "Received items" -msgstr "Elemente empfangen" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "Firma an die die Teile verkauft werden" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "Kundenreferenz" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "Bestellreferenz" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "Versanddatum" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "Versand von" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "Bestellung kann nicht versendet werden weil er nicht anhängig ist" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "Anzahl" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "Position - Referenz" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "Position - Notizen" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "Bestellung" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "Bestellung" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" -msgstr "Zulieferer-Teil" +msgstr "Zuliefererteil" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "Empfangen" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "Empfangene Objekt-Anzahl" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "Preis" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "Preis pro Einheit" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "Verkaufspreis" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "Stückverkaufspreis" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "BestandsObjekt wurde nicht zugewiesen" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "Kann BestandsObjekt keiner Zeile mit einem anderen Teil hinzufügen" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "Kann BestandsObjekt keiner Zeile ohne Teil hinzufügen" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "Die zugeordnete Anzahl darf nicht die verfügbare Anzahl überschreiten" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "Anzahl für BestandsObjekt mit Seriennummer muss 1 sein" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "Position" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "Position" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "BestandsObjekt für Zuordnung auswählen" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "Anzahl für Bestandszuordnung eingeben" @@ -2836,7 +2982,7 @@ msgstr "Aufgegeben" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "Neuer Lagerort" @@ -2847,10 +2993,8 @@ msgid "Create new stock location" msgstr "Neuen Lagerort anlegen" #: order/templates/order/order_cancel.html:8 -#, fuzzy -#| msgid "Cancelling this order means that the order will no longer be editable." msgid "Cancelling this order means that the order and line items will no longer be editable." -msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar ist." +msgstr "Abbruch dieser Bestellung bedeutet, dass sie und ihre Positionen nicht länger bearbeitbar sind." #: order/templates/order/order_complete.html:7 msgid "Mark this order as complete?" @@ -2861,10 +3005,8 @@ msgid "This order has line items which have not been marked as received." msgstr "Diese Bestellung enthält Positionen, die nicht als empfangen markiert wurden." #: order/templates/order/order_complete.html:11 -#, fuzzy -#| msgid "Cancelling this order means that the order will no longer be editable." msgid "Completing this order means that the order and line items will no longer be editable." -msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar ist." +msgstr "Fertigstellen dieser Bestellung bedeutet, dass sie und ihre Positionen nicht länger bearbeitbar sind." #: order/templates/order/order_issue.html:8 msgid "After placing this purchase order, line items will no longer be editable." @@ -2874,6 +3016,75 @@ msgstr "Nachdem diese Bestellung plaziert ist können die Positionen nicht läng msgid "Order Notes" msgstr "Notizen zur Bestellung" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "Es fehlt eine Auswahl für die folgende benötigte Spalte" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "Doppelte Auswahlen gefunden, siehe unten. Reparieren und erneut versuchen." + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "Vorheriger Schritt" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "Auswahl übertragen" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "Datei-Felder" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "Spalte entfernen" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "Auswahl duplizieren" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "Zeile entfernen" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "Fehler in den übermittelten Daten" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "Zeile" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "Zulieferer-Teil auswählen" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "Datei zur Bestellung hochladen" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "Schritt %(step)s von %(count)s" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "Bestellung ist bereits verarbeitet. Dateien können nicht hochgeladen werden." + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "Schritt 1 von 2 - Zulieferer auswählen" @@ -2918,16 +3129,14 @@ msgid "Select Purchase Order" msgstr "Bestellung auswählen" #: order/templates/order/order_wizard/select_pos.html:45 -#, fuzzy, python-format -#| msgid "Create new purchase order" +#, python-format msgid "Create new purchase order for %(name)s" -msgstr "Neue Bestellung anlegen" +msgstr "Neue Bestellung für %(name)s anlegen" #: order/templates/order/order_wizard/select_pos.html:68 -#, fuzzy, python-format -#| msgid "Select a purchase order for" +#, python-format msgid "Select a purchase order for %(name)s" -msgstr "Bestellung auswählen für" +msgstr "Bestellung für %(name)s auswählen" #: order/templates/order/po_attachments.html:12 #: order/templates/order/po_navbar.html:23 @@ -2948,8 +3157,8 @@ msgid "Purchase Order Items" msgstr "Bestellungs-Positionen" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "Position hinzufügen" @@ -2958,11 +3167,12 @@ msgid "No line items found" msgstr "Keine Positionen gefunden" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "Stück-Preis" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "Position bearbeiten" @@ -2992,7 +3202,7 @@ msgstr "Ausstehende Teile für %(order)s - %(desc)s empfangen" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "Teile" @@ -3008,7 +3218,7 @@ msgstr "Bestellnummer" #: order/templates/order/receive_parts.html:21 #: part/templates/part/part_base.html:129 templates/js/part.js:414 msgid "On Order" -msgstr "bestellt" +msgstr "Bestellt" #: order/templates/order/receive_parts.html:23 msgid "Receive" @@ -3054,59 +3264,72 @@ msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar i msgid "Sales Order Items" msgstr "Auftrags-Positionen" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "Aktionen" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "Bestands-Zuordnung bearbeiten" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "Bestands-Zuordnung löschen" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "Keine passenden Positionen gefunden" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "ID" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "Zugeordnet" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "Erledigt" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "PO" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "Seriennummern zuweisen" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "Lagerbestand zuweisen" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "Lagerbestand kaufen" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "Lagerbestand bauen" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "Preis berechnen" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "Position löschen " +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "Stückpreis aktualisieren" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "Auftrags-Positionen" @@ -3148,164 +3371,189 @@ msgstr "Auftrags-Anhänge" msgid "Are you sure you wish to delete this line item?" msgstr "Sind Sie sicher, dass Sie diese Position löschen möchten?" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "Bestellungs-Anhang hinzufügen" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "Auftrags-Anhang hinzufügen" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "Auftrag anlegen" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "Bestellung bearbeiten" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "Auftrag bearbeiten" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "Bestellung stornieren" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "Bestellstornierung bestätigen" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "Bestellung kann nicht verworfen werden" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "Auftrag stornieren" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "Bestellung aufgeben" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "Bestellungstätigung bestätigen" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" -msgstr "Bestellung erstellt" +msgstr "Bestellung plaziert" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "Auftrag fertigstellen" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "Fertigstellung bestätigen" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "Bestellung als vollständig markieren" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "Versenden" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "Versand bestätigen" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "Versand fehlgeschlagen" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "Zuliefererteile zuordnen" + +#: order/views.py:798 msgid "Receive Parts" msgstr "Teile empfangen" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "Anzahl empfangener Positionen" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "Kein Ziel gesetzt" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "Fehler beim Konvertieren zu Zahl" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "Anzahl kleiner null empfangen" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "Keine Zeilen angegeben" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "{n} Teile bestellt" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" -msgstr "Zulieferer-Teil muss ausgewählt werden" +msgstr "Zuliefererteil muss ausgewählt werden" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "Zulieferer muss zu Teil und Bestellung passen" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "Position bearbeiten" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "Position löschen" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "Position gelöscht" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "Seriennummern zuweisen" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "{n} Positionen zugeordnet" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "Position auswählen" -#: order/views.py:1410 -msgid "No matching item for serial" -msgstr "Kein passends Teil für Seriennummer gefunden" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" +msgstr "Kein passends Teil für Seriennummer {serial} gefunden" -#: order/views.py:1420 -msgid "is not in stock" -msgstr "ist nicht auf Lager" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" +msgstr "{serial} ist nicht auf Lager" -#: order/views.py:1428 -msgid "already allocated to an order" -msgstr "bereits einem Auftrag zugeordnet" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" +msgstr "{serial} bereits einem Auftrag zugeordnet" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "Lagerbestand dem Auftrag zuweisen" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "Zuordnung bearbeiten" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "Zuordnung entfernen" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "Auftrag nicht gefunden" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "Preis nicht gefunden" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "Stückpreis für {part} auf {price} aktualisiert" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "{part} Stückpreis auf {price} und Menge auf {qty} aktualisiert" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3384,7 +3632,7 @@ msgstr "Zulieferer einschließen" msgid "Include part supplier data in exported BOM" msgstr "Zulieferer-Daten in Stückliste-Export einschließen" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "Ausgangsteil" @@ -3460,7 +3708,7 @@ msgstr "Parameter-Vorlage zu Kategorien dieser Ebene hinzufügen" msgid "Add parameter template to all categories" msgstr "Parameter-Vorlage zu allen Kategorien hinzufügen" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "Untergeordnetes Teil" @@ -3480,14 +3728,14 @@ msgstr "Standard Stichwörter" msgid "Default keywords for parts in this category" msgstr "Standard-Stichworte für Teile dieser Kategorie" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "Teil-Kategorie" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "Teil-Kategorien" @@ -3550,7 +3798,7 @@ msgstr "Schlüsselwörter" msgid "Part keywords to improve visibility in search results" msgstr "Schlüsselworte um die Sichtbarkeit in Suchergebnissen zu verbessern" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "Kategorie" @@ -3587,7 +3835,7 @@ msgstr "Standard Zulieferer" #: part/models.py:808 msgid "Default supplier part" -msgstr "Standard Zulieferer-Teil" +msgstr "Standard Zuliefererteil" #: part/models.py:815 msgid "Default Expiry" @@ -3605,7 +3853,7 @@ msgstr "Minimaler Lagerbestand" msgid "Minimum allowed stock level" msgstr "Minimal zulässiger Lagerbestand" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "Einheiten" @@ -3635,8 +3883,8 @@ msgid "Can this part be sold to customers?" msgstr "Kann dieses Teil an Kunden verkauft werden?" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "Aktiv" @@ -3672,167 +3920,171 @@ msgstr "BOM Kontrolldatum" msgid "Creation User" msgstr "Erstellungs-Nutzer" -#: part/models.py:1949 +#: part/models.py:1616 +msgid "Sell multiple" +msgstr "Mehrere verkaufen" + +#: part/models.py:1987 msgid "Test templates can only be created for trackable parts" msgstr "Test-Vorlagen können nur für verfolgbare Teile angelegt werden" -#: part/models.py:1966 +#: part/models.py:2004 msgid "Test with this name already exists for this part" msgstr "Ein Test mit diesem Namen besteht bereits für dieses Teil" -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "Test-Name" -#: part/models.py:1987 +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "Namen für diesen Test eingeben" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "Test-Beschreibung" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "Beschreibung für diesen Test eingeben" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" -msgstr "benötigt" +msgstr "Benötigt" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "Muss dieser Test erfolgreich sein?" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" -msgstr "verpflichtender Wert" +msgstr "Erfordert Wert" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "Muss für diesen Test ein Wert für das Test-Ergebnis eingetragen werden?" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "Anhang muss eingegeben werden" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "Muss für diesen Test ein Anhang für das Test-Ergebnis hinzugefügt werden?" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "Vorlagen-Name des Parameters muss eindeutig sein" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "Name des Parameters" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" -msgstr "Parameter Einheit" +msgstr "Einheit des Parameters" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "Parameter Vorlage" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "Wert" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "Parameter Wert" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "Standard-Wert" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "Standard Parameter Wert" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "Ausgangsteil auswählen" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "Optional" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "Diese Stücklisten-Position ist optional" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "Überschuss" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "Referenz der Postion auf der Stückliste" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "Notizen zur Stücklisten-Position" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "Prüfsumme" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "Geerbt" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "Diese Stücklisten-Position wird in die Stücklisten von Teil-Varianten vererbt" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "Menge muss eine Ganzzahl sein" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" -msgstr "Zulieferer-Teil muss festgelegt sein" +msgstr "Zuliefererteil muss festgelegt sein" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "Stücklisten-Position" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "Teil 1" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "Teil 2" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "verknüpftes Teil auswählen" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "Fehler bei Verwandschaft: Ist das Teil mit sich selbst verwandt oder ist das die Verwandtschaft nicht eindeutig?" @@ -3917,7 +4169,7 @@ msgid "All selected BOM items will be deleted" msgstr "Alle ausgewählte Stücklistenpositionen werden gelöscht" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "Neues Teil anlegen" @@ -3935,51 +4187,18 @@ msgstr "Stückliste hochladen" msgid "Step 2 - Select Fields" msgstr "Schritt 2 - Felder auswählen" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "Es fehlt eine Auswahl für die folgende benötigte Spalte" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "Auswahl übertragen" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "Datei-Felder" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "Spalte entfernen" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "Übereinstimmende Felder" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "Spalte doppelt ausgewählt" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "Zeile entfernen" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "Schritt 3 - Teile auswählen" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "Fehler in den übermittelten Daten" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "Stückliste abschicken" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "Zeile" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -4010,10 +4229,6 @@ msgstr "Vorlage für Stückliste" msgid "Each part must already exist in the database" msgstr "Jedes Teil muss bereits in der Datenbank bestehen" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "Datei hochgeladen" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4025,7 +4240,7 @@ msgstr "Damit wird jede Zeile der Stückliste kontrolliert" #: part/templates/part/build.html:10 msgid "Part Builds" -msgstr "gefertigte Teile" +msgstr "Gefertigte Teile" #: part/templates/part/build.html:18 msgid "Start New Build" @@ -4035,7 +4250,7 @@ msgstr "Neuen Bauauftrag beginnen" msgid "All parts" msgstr "Alle Teile" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "Teil-Kategorie anlegen" @@ -4103,7 +4318,7 @@ msgstr "Teil-Kategorie anlegen" msgid "Create new Part Category" msgstr "Neue Teil-Kategorie anlegen" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "Neuen Lagerort erstellen" @@ -4136,7 +4351,7 @@ msgstr "Diese Kategorie enthält %(count)s Teile" #: part/templates/part/category_delete.html:27 #, python-format msgid "If this category is deleted, these parts will be moved to the parent category %(path)s" -msgstr "Wenn diese Kat. gelöscht wird, werden diese Teile in die übergeordnete Kat. %(path)s verschoben" +msgstr "Wenn diese Kat. gelöscht wird, werden diese Teile in die übergeordnete Kategorie %(path)s verschoben" #: part/templates/part/category_delete.html:29 msgid "If this category is deleted, these parts will be moved to the top-level category Teile" @@ -4179,7 +4394,7 @@ msgstr "%(full_name)s - %(desc)s (%(match_per)s%% übereinstimmend)" #: part/templates/part/detail.html:11 part/templates/part/navbar.html:11 msgid "Part Details" -msgstr "Teile-Details" +msgstr "Teil Details" #: part/templates/part/detail.html:42 msgid "Latest Serial Number" @@ -4294,22 +4509,18 @@ msgstr "Benutzt in" msgid "Sales Price Information" msgstr "Preisinformationen ansehen" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "VK-Preis" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "Teil Test-Vorlagen" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "Tests" #: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 #: part/templates/part/related.html:10 msgid "Related Parts" -msgstr "verknüpfte Teile" +msgstr "Verknüpfte Teile" #: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 msgid "Part Notes" @@ -4327,7 +4538,7 @@ msgstr "Neuer Parameter" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "Wert" @@ -4363,19 +4574,19 @@ msgid "Star this part" msgstr "Teil favorisieren" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "Barcode Aktionen" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "QR-Code anzeigen" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "Label drucken" @@ -4404,7 +4615,7 @@ msgstr "Teil bearbeiten" msgid "Delete part" msgstr "Teil löschen" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "Auf Lager" @@ -4418,7 +4629,7 @@ msgstr "Benötigt für Aufträge" #: part/templates/part/part_base.html:150 msgid "Allocated to Orders" -msgstr "zu Bauaufträgen zugeordnet" +msgstr "Zu Bauaufträgen zugeordnet" #: part/templates/part/part_base.html:165 templates/js/bom.js:300 msgid "Can Build" @@ -4432,42 +4643,39 @@ msgstr "Im Bau" msgid "Calculate" msgstr "Berechnen" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "Preisinformationen für:
    %(part)s." - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "Zulieferer-Preise" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "Stückpreis" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "Gesamtkosten" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "Keine Zulieferer-Preise verfügbar" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "Stücklistenpreise" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "Anmerkung: Stücklistenbepreisung für dieses Teil ist unvollständig" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "Keine Stücklisten-Preise verfügbar" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "Keine Preise für dieses Teil verfügbar" @@ -4511,11 +4719,11 @@ msgstr "Es gibt %(count)s einzigartige Teile, die für '%(full_name)s' verfolgt #: part/templates/part/related.html:18 msgid "Add Related" -msgstr "Zugehöriges Teil hinzufügen" +msgstr "Verknüpftes Teil hinzufügen" #: part/templates/part/sale_prices.html:10 msgid "Sell Price Information" -msgstr "VK-Preis Informationen" +msgstr "Verkaufspreis Informationen" #: part/templates/part/sales_orders.html:18 msgid "New sales order" @@ -4576,6 +4784,10 @@ msgstr "Neue Variante anlegen" msgid "New Variant" msgstr "neue Variante anlegen" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "Unbekannte Datenbank" + #: part/views.py:89 msgid "Add Related Part" msgstr "verknüpftes Teil hinzufügen" @@ -4725,63 +4937,63 @@ msgstr "Teil wurde gelöscht" msgid "Part Pricing" msgstr "Teilbepreisung" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "Teilparametervorlage bearbeiten" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "Teilparametervorlage löschen" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "Teilparameter anlegen" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "Teilparameter bearbeiten" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "Teilparameter löschen" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "Teil-Kategorie bearbeiten" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "Teil-Kategorie löschen" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "Teil-Kategorie wurde gelöscht" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "Kategorieparametervorlage anlegen" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "Kategorieparametervorlage bearbeiten" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "Kategorieparametervorlage löschen" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "Stücklisten-Position anlegen" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "Stücklisten-Position bearbeiten" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "löschen von Stücklisten-Position bestätigen" @@ -4883,17 +5095,17 @@ msgid "Test Results" msgstr "Testergebnisse" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "Test" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "Ergebnis" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "Datum" @@ -4905,22 +5117,22 @@ msgstr "bestanden" msgid "Fail" msgstr "fehlgeschlagen" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "Bestand für {n} Objekte geändert" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "{n} Teile nach {loc} bewegt" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "Ablaufdatum" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "Ablaufdatum für dieses BestandsObjekt" @@ -4948,8 +5160,8 @@ msgstr " Transaktionsnotizen hinzufügen (optional)" msgid "Select test report template" msgstr "Test Bericht Vorlage auswählen" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "Unter-Lagerorte einschließen" @@ -5005,243 +5217,187 @@ msgstr "Standard-Lagerort ändern" msgid "Set the destination as the default location for selected parts" msgstr "Setze das Ziel als Standard-Lagerort für ausgewählte Teile" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "Besitzer" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "Besitzer auswählen" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "Neues BestandsObjekt erstellt" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "Ein BestandsObjekt mit dieser Seriennummer existiert bereits" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "Teile-Typ ('{pf}') muss {pe} sein" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "Anzahl muss für Objekte mit Seriennummer 1 sein" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "Seriennummer kann nicht gesetzt werden wenn die Anzahl größer als 1 ist" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "Teil kann nicht zu sich selbst gehören" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "Teil muss eine Referenz haben wenn is_building wahr ist" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "Referenz verweist nicht auf das gleiche Teil" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "Eltern-BestandsObjekt" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "Basis-Teil" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" -msgstr "Passendes Zulieferer-Teil für dieses BestandsObjekt auswählen" +msgstr "Passendes Zuliefererteil für dieses BestandsObjekt auswählen" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "Bestand-Lagerort" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "Wo wird dieses Teil normalerweise gelagert?" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "Die Verpackung dieses BestandsObjekt ist gelagert in" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "verbaut in" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "Ist dieses Teil in einem anderen verbaut?" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "Seriennummer für dieses Teil" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "Losnummer für dieses BestandsObjekt" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "Bestand" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "Quellbau" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "Bauauftrag für dieses BestandsObjekt" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "Quelle Bestellung" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "Bestellung für dieses BestandsObjekt" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "Ziel-Auftrag" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "Ablaufdatum für BestandsObjekt. Bestand wird danach als abgelaufen gekennzeichnet" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "Löschen wenn leer" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "Dieses BestandsObjekt löschen wenn Bestand aufgebraucht" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "BestandsObjekt-Notizen" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "Preis für eine Einheit bei Einkauf" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "zugewiesen zum Kunden" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "manuell zugewiesen zum Kunden" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "zurück vom Kunden" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "zurück ins Lager" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "In BestandsObjekt verbaut" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "verbautes BestandsObjekt" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "BestandsObjekt ausgebaut" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "ausgebaut nach Lagerort" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "Teil ist nicht verfolgbar" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "Anzahl muss eine Ganzzahl sein" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "Anzahl darf nicht die verfügbare Anzahl überschreiten ({n})" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "Seriennummern muss eine Liste von Ganzzahlen sein" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "Anzahl stimmt nicht mit den Seriennummern überein" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "Seriennummer hinzufügen" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" -msgstr "{n} Teile serialisiert" +msgid "Serial numbers already exist: {exists}" +msgstr "Seriennummern {exists} existieren bereits" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "aufteilen vom vorhandenen Bestand" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "BestandsObjekt kann nicht bewegt werden, da kein Bestand vorhanden ist" -#: stock/models.py:1556 -msgid "Title" -msgstr "Titel" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "Objektverfolgung - Name des Eintrags" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "Eintrags-Notizen" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "Link auf externe Seite für weitere Informationen" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "Wert muss für diesen Test angegeben werden" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "Anhang muss für diesen Test hochgeladen werden" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "Name des Tests" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "Testergebnis" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "Test Ausgabe Wert" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "Test Ergebnis Anhang" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "Test Notizen" @@ -5296,134 +5452,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "Dieses BestandsObjekt wird automatisch gelöscht wenn der Lagerbestand aufgebraucht ist." #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "abgelaufen" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "überfällig" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "Barcode abhängen" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "Barcode anhängen" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "zu Lagerort einscannen" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "Druck Aktionen" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "Test-Bericht" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "Bestands-Anpassungs Aktionen" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "Bestand zählen" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "Bestand hinzufügen" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "Bestand entfernen" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "Lagerbestand serialisieren" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "Bestand verschieben" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" -msgstr "zu Kunden zuordnen" +msgstr "Kunden zuweisen" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "zu Bestand zurückgeben" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "BestandsObjekt deinstallieren" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "Deinstallieren" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "Bestands-Aktionen" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "in Variante ändern" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "BestandsObjekt duplizieren" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "BestandsObjekt bearbeiten" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "BestandsObjekt löschen" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "BestandsObjekt-Details" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "Kein Lagerort gesetzt" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "Barcode-Bezeichner" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "Elternposition" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "Dieses BestandsObjekt lief am %(item.expiry_date)s ab" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "Dieses BestandsObjekt läuft am %(item.expiry_date)s ab" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "Zuletzt aktualisiert" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "Letzte Inventur" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "Keine Inventur ausgeführt" @@ -5467,7 +5623,7 @@ msgstr "Installierte BestandsObjekte" #: stock/templates/stock/item_serialize.html:5 msgid "Create serialized items from this stock item." -msgstr "Teile mit Seriennummern von diesem BestandObjekt anlegen." +msgstr "Teile mit Seriennummern mit diesem BestandObjekt anlegen." #: stock/templates/stock/item_serialize.html:7 msgid "Select quantity to serialize, and unique serial numbers." @@ -5534,7 +5690,7 @@ msgid "Stock Details" msgstr "Objekt-Details" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "Bestand-Lagerorte" @@ -5574,7 +5730,7 @@ msgstr "Lade..." msgid "The following stock items will be uninstalled" msgstr "Die folgenden BestandsObjekte werden nicht mehr verbaut" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "BestandsObjekt umwandeln" @@ -5607,8 +5763,8 @@ msgstr "Sind Sie sicher, dass Sie diesen BestandsObjekt-Verfolgungs-Eintrag lös msgid "Edit Stock Location" msgstr "BestandsObjekt-Lagerort bearbeiten" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "Eigentümer notwendig (Eigentümerkontrolle aktiv)" @@ -5630,7 +5786,7 @@ msgstr "BestandsObjekt-Anhang löschen" #: stock/views.py:343 msgid "Assign to Customer" -msgstr "einem Kunden zuordnen" +msgstr "Kunden zuweisen" #: stock/views.py:352 msgid "Customer must be specified" @@ -5774,43 +5930,47 @@ msgstr "{n} Teile nach {dest} bewegt" msgid "Deleted {n} stock items" msgstr "{n} BestandsObjekte gelöscht" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "Lagerbestandsstatus bearbeiten" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "BestandsObjekt bearbeiten" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "Lagerbestand erfassen" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "Neues BestandsObjekt hinzufügen" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "Bestand duplizieren" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "Anzahl kann nicht negativ sein" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "Bestand-Lagerort löschen" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "BestandsObjekt löschen" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag löschen" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag bearbeiten" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag hinzufügen" @@ -5907,30 +6067,23 @@ msgid "Color Themes" msgstr "Farbschemata" #: templates/InvenTree/settings/appearance.html:29 -#, fuzzy, python-format -#| msgid "" -#| "\n" -#| "\t\tThe CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" -#| "\t\tPlease select another color theme :)\n" -#| "\t" -msgid "" -"\n" +#, python-format +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " -msgstr "" -"\n" +msgstr "\n" "\t\tDie CSS Datei \"%(invalid_color_theme)s.css\" für das aktuell ausgewählte Farbschema wurde nicht gefunden.
    \n" "\t\tBitte ein anderes Farbschema auswählen:)\n" -"\t" +"\t " #: templates/InvenTree/settings/appearance.html:39 msgid "Language" -msgstr "" +msgstr "Sprache" #: templates/InvenTree/settings/appearance.html:61 msgid "Set Language" -msgstr "" +msgstr "Sprache festlegen" #: templates/InvenTree/settings/build.html:10 msgid "Build Order Settings" @@ -6017,7 +6170,7 @@ msgstr "Bestands-Einstellungen" #: templates/InvenTree/settings/stock.html:13 templates/stock_table.html:50 msgid "Stock Options" -msgstr "Stock-Optionen" +msgstr "Bestands-Einstellungen " #: templates/InvenTree/settings/tabs.html:3 #: templates/InvenTree/settings/user.html:10 @@ -6030,7 +6183,7 @@ msgstr "Konto" #: templates/InvenTree/settings/tabs.html:9 msgid "Appearance" -msgstr "" +msgstr "Anzeige" #: templates/InvenTree/settings/tabs.html:13 msgid "InvenTree Settings" @@ -6111,19 +6264,27 @@ msgstr "Code auf GitHub ansehen" #: templates/about.html:63 msgid "Credits" -msgstr "" +msgstr "Danksagung" #: templates/about.html:68 msgid "Mobile App" -msgstr "" +msgstr "Mobile App" #: templates/about.html:73 msgid "Submit Bug Report" msgstr "Fehlerbericht senden" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "In die Zwischenablage kopieren" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "Versionsinformationen kopieren" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "Schliessen" @@ -6131,10 +6292,6 @@ msgstr "Schliessen" msgid "Add Attachment" msgstr "Anhang hinzufügen" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "Datei" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "Hochgeladen" @@ -6187,7 +6344,7 @@ msgstr "Server-Fehler" msgid "Unknown response from server" msgstr "Unbekannte Antwort von Server erhalten" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "Ungültige Antwort von Server" @@ -6295,7 +6452,7 @@ msgstr "Keine Stücklisten-Position(en) gefunden" #: templates/js/build.js:62 msgid "Auto-allocate stock items to this output" -msgstr "BestandsObjekte automatisch Endprodukt zuordnen" +msgstr "Teilbestand automatisch Endprodukt zuweisen" #: templates/js/build.js:70 msgid "Unallocate stock from build output" @@ -6332,7 +6489,7 @@ msgstr "Keine Bauaufträge passen zur Anfrage" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "Auswählen" @@ -6350,7 +6507,7 @@ msgstr "Teile geliefert" #: templates/js/company.js:83 msgid "Parts Manufactured" -msgstr "Teile gefertigt" +msgstr "Hersteller-Teile" #: templates/js/company.js:96 msgid "No company information found" @@ -6372,7 +6529,7 @@ msgstr "Baugruppe" #: templates/js/company.js:227 msgid "No supplier parts found" -msgstr "Keine Zulieferer-Teile gefunden" +msgstr "Keine Zuliefererteile gefunden" #: templates/js/filters.js:193 msgid "Select filter" @@ -6430,96 +6587,96 @@ msgstr "Label auswählen" msgid "Select Label Template" msgstr "Label-Vorlage auswählen" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "Warte auf Server..." -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "Fehler-Informationen anzeigen" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "Akzeptieren" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "abbrechen" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "Lade Daten" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "Abschicken" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "ungültige Antwort vom Server" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "Formulardaten fehlen bei Serverantwort" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "Formulardaten fehlerhaft" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "JSON Antwort enthält keine Formulardaten" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "Keine Antwort" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "keine Antwort vom InvenTree Server" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "Fehler 400: Ungültige Anfrage" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "Fehler 400 von Server erhalten" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "Fehler 401: Nicht Angemeldet" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "Authentication Kredentials nicht angegeben" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "Fehler 403: keine Berechtigung" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "Fehlende Berechtigung für diese Aktion" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "Fehler 404: Ressource nicht gefunden" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "Die angefragte Ressource kann auf diesem Server nicht gefunden werden" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "Fehler 408: Zeitüberschreitung" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "Verbindungszeitüberschreitung bei der Datenanforderung" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "Fehler bei Formulardaten-Anfrage" @@ -6537,7 +6694,7 @@ msgstr "Keine Aufträge gefunden" #: templates/js/part.js:52 templates/js/part.js:137 msgid "Trackable part" -msgstr "nachverfolgbares Teil" +msgstr "Nachverfolgbares Teil" #: templates/js/part.js:56 templates/js/part.js:141 msgid "Virtual part" @@ -6563,7 +6720,7 @@ msgstr "Keine Teile gefunden" msgid "No category" msgstr "Keine Kategorie" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "Bestand niedrig" @@ -6715,7 +6872,7 @@ msgstr "lose" #: templates/js/stock.js:476 msgid "locations" -msgstr "lagerorte" +msgstr "Lagerorte" #: templates/js/stock.js:478 msgid "Undefined location" @@ -6761,7 +6918,7 @@ msgstr "BestandsObjekt verloren" msgid "Stock item is destroyed" msgstr "BestandsObjekt zerstört" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "gelöscht" @@ -6785,189 +6942,213 @@ msgstr "Status Code setzen" msgid "Status code must be selected" msgstr "Status Code muss ausgewählt werden" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "Ungültiges Datum" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "Standort nicht mehr vorhanden" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "Bestellung existiert nicht mehr" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "Kunde existiert nicht mehr" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "Lagerbestand existiert nicht mehr" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "Hinzugefügt" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "Entfernt" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "Keine Benutzerinformation" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "Tracking-Eintrag bearbeiten" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "Tracking-Eintrag löschen" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "Neuen Lagerort anlegen" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "Seriennummer" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "Installiert" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "Installiere Objekt" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" -msgstr "nachverfolgbares Teil" +msgstr "Nachverfolgbares Teil" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "überprüft" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "Lagerorte einschließen" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "Unterkategorien einschließen" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" -msgstr "ist mit Seriennummer" +msgstr "Hat Seriennummer" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "Seriennummer >=" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "Seriennummer größer oder gleich" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "Seriennummer <=" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "Seriennummern kleiner oder gleich" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "Seriennummer" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "Losnummer" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "Aktive Teile" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "Bestand aktiver Teile anzeigen" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "Teil ist eine Baugruppe" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "Ist zugeordnet" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "Teil wurde zugeordnet" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "Bestand in Unter-Lagerorten einschließen" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "Zeige aufgebrauchte BestandsObjekte" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "Zeige abgelaufene BestandsObjekte" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "Bestand, der bald ablaufen, anzeigen" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "Zeige Objekte welche im Lager sind" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "In Arbeit" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "Elemente, die in Produktion sind, anzeigen" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "Varianten einschließen" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "BestandsObjekte für Teil-Varianten einschließen" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "BestandsObjekte, die in anderen Elementen verbaut sind, anzeigen" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "Zum Kunden geschickt" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "zeige zu Kunden zugeordnete Einträge" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "Bestandsstatus" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "Bauauftrags-Status" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "Bestellstatus" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "ausstehend" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "Teile in Unterkategorien einschließen" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "Hat IPN" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "Teil hat Interne Teilenummer" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "Aktive Teile anzeigen" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "verfügbarer Lagerbestand" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "Favorit" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "Käuflich" @@ -7024,13 +7205,13 @@ msgstr "Spalten" msgid "All" msgstr "Alle" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "Fehler in Formular" #: templates/navbar.html:13 msgid "Toggle navigation" -msgstr "" +msgstr "Navigation ein-/ausklappen" #: templates/navbar.html:33 msgid "Buy" @@ -7058,7 +7239,7 @@ msgstr "Einloggen" #: templates/navbar.html:104 msgid "About InvenTree" -msgstr "Über InvenBaum" +msgstr "Über InvenTree" #: templates/qr_code.html:11 msgid "QR data not provided" @@ -7136,31 +7317,47 @@ msgstr "Server" msgid "Instance Name" msgstr "Instanzname" -#: templates/stats.html:19 +#: templates/stats.html:18 +msgid "Database" +msgstr "Datenbank" + +#: templates/stats.html:26 +msgid "Server is running in debug mode" +msgstr "Server läuft im Debug-Modus" + +#: templates/stats.html:33 +msgid "Docker Mode" +msgstr "" + +#: templates/stats.html:34 +msgid "Server is deployed using docker" +msgstr "" + +#: templates/stats.html:40 msgid "Server status" msgstr "Serverstatus" -#: templates/stats.html:22 +#: templates/stats.html:43 msgid "Healthy" msgstr "Gesund" -#: templates/stats.html:24 +#: templates/stats.html:45 msgid "Issues detected" msgstr "Probleme erkannt" -#: templates/stats.html:31 +#: templates/stats.html:52 msgid "Background Worker" msgstr "Hintergrund-Prozess" -#: templates/stats.html:34 +#: templates/stats.html:55 msgid "Background worker not running" msgstr "Hintergrund-Prozess läuft nicht" -#: templates/stats.html:42 +#: templates/stats.html:63 msgid "Email Settings" msgstr "E-Mail-Einstellungen" -#: templates/stats.html:45 +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "E-Mail-Einstellungen nicht konfiguriert" @@ -7280,14 +7477,3 @@ msgstr "Berechtigungen Einträge zu ändern" msgid "Permission to delete items" msgstr "Berechtigung Einträge zu löschen" -#~ msgid "Marking this order as complete will remove these line items." -#~ msgstr "Wenn Sie diese Bestellung als abgeschlossen markieren, werden diese Positionen entfernt." - -#~ msgid "Create new purchase order for {{ supplier.name }}" -#~ msgstr "Neue Bestellung für {{ supplier.name }} anlegen" - -#~ msgid "Theme" -#~ msgstr "Thema" - -#~ msgid "Get the App" -#~ msgstr "App herunterladen" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 097f4c0f8c..7e057e4153 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -78,8 +78,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -107,7 +107,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -123,9 +123,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "" @@ -133,8 +133,8 @@ msgstr "" msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -142,11 +142,11 @@ msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -160,7 +160,7 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "" @@ -172,23 +172,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -204,60 +204,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -276,7 +352,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -382,35 +459,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -422,7 +499,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -452,11 +529,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -465,12 +542,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -523,9 +601,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -547,16 +625,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -566,7 +644,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -622,7 +700,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -635,7 +713,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -673,28 +751,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -716,75 +794,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -818,7 +892,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -838,9 +912,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -903,7 +977,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -914,8 +988,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -961,14 +1035,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1118,9 +1192,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1174,6 +1248,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1208,7 +1283,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1237,7 +1313,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1354,372 +1430,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1727,24 +1836,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1764,216 +1891,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1999,7 +2126,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2045,10 +2172,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2094,7 +2222,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2141,19 +2269,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2211,7 +2339,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2264,7 +2392,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2319,8 +2447,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2369,7 +2497,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2399,7 +2527,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2419,6 +2547,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2439,7 +2572,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2471,7 +2604,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2479,15 +2612,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2495,51 +2628,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2577,15 +2718,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2613,7 +2754,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2654,8 +2795,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2663,128 +2804,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2836,7 +2983,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2870,6 +3017,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2942,8 +3158,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2952,11 +3168,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2986,7 +3203,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3048,59 +3265,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3142,164 +3372,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3378,7 +3633,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3454,7 +3709,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3474,14 +3729,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3544,7 +3799,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3599,7 +3854,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3629,8 +3884,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3666,167 +3921,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3911,7 +4170,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3929,51 +4188,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -4004,10 +4230,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4029,7 +4251,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4097,7 +4319,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4288,15 +4510,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4321,7 +4539,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4357,19 +4575,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4398,7 +4616,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4426,42 +4644,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4570,6 +4785,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4719,63 +4938,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4877,17 +5096,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4899,22 +5118,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4942,8 +5161,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4999,243 +5218,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5290,134 +5453,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5528,7 +5691,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5568,7 +5731,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5601,8 +5764,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5768,43 +5931,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -6106,9 +6273,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6116,10 +6291,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6172,7 +6343,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6317,7 +6488,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6415,96 +6586,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6548,7 +6719,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6746,7 +6917,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6770,189 +6941,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7009,7 +7204,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7121,31 +7316,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index 459ce5092a..f56eb19904 100644 --- a/InvenTree/locale/es/LC_MESSAGES/django.po +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: Spanish\n" "Language: es_ES\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: es-ES\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -33,7 +38,7 @@ msgstr "" #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" -msgstr "" +msgstr "Confirmar" #: InvenTree/forms.py:126 msgid "Confirm delete" @@ -53,11 +58,11 @@ msgstr "" #: InvenTree/forms.py:167 msgid "Confirm password" -msgstr "" +msgstr "Confirmar la contraseña" #: InvenTree/forms.py:168 msgid "Confirm new password" -msgstr "" +msgstr "Confirmar contraseña nueva" #: InvenTree/forms.py:203 msgid "Apply Theme" @@ -72,8 +77,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -101,7 +106,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -111,36 +116,36 @@ msgstr "" #: InvenTree/models.py:62 templates/attachment_table.html:16 msgid "Comment" -msgstr "" +msgstr "Comentario" #: InvenTree/models.py:62 msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" -msgstr "" +msgstr "Usuario" #: InvenTree/models.py:72 msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 msgid "Name" -msgstr "" +msgstr "Nombre" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,9 +159,9 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" -msgstr "" +msgstr "Descripción" #: InvenTree/models.py:115 msgid "Description (optional)" @@ -166,25 +171,25 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" -msgstr "" +msgstr "Inglés" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" -msgstr "" +msgstr "Francés" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" -msgstr "" +msgstr "Alemán" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" -msgstr "" +msgstr "Polaco" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" -msgstr "" +msgstr "Turco" #: InvenTree/status.py:93 msgid "Background worker check failed" @@ -198,63 +203,139 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" -msgstr "" - -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 -msgid "Cancelled" -msgstr "" - -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 -msgid "Lost" -msgstr "" +msgstr "Terminado" #: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 +msgid "Cancelled" +msgstr "Cancelado" + +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 #: InvenTree/status_codes.py:190 +msgid "Lost" +msgstr "Perdida" + +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 -msgid "OK" -msgstr "" - -#: InvenTree/status_codes.py:185 -msgid "Attention needed" -msgstr "" - #: InvenTree/status_codes.py:186 -msgid "Damaged" -msgstr "" +msgid "OK" +msgstr "OK" #: InvenTree/status_codes.py:187 -msgid "Destroyed" -msgstr "" +msgid "Attention needed" +msgstr "Atención necesaria" + +#: InvenTree/status_codes.py:188 +msgid "Damaged" +msgstr "Dañado" #: InvenTree/status_codes.py:189 +msgid "Destroyed" +msgstr "Destruido" + +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 -msgid "Production" +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" msgstr "" +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 +msgid "Production" +msgstr "Producción" + #: InvenTree/validators.py:22 msgid "Not a valid currency code" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -292,7 +374,7 @@ msgstr "" #: InvenTree/views.py:587 msgid "Delete Item" -msgstr "" +msgstr "Eliminar elemento" #: InvenTree/views.py:636 msgid "Check box to confirm item deletion" @@ -304,7 +386,7 @@ msgstr "" #: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 msgid "Set Password" -msgstr "" +msgstr "Configurar Contraseña" #: InvenTree/views.py:681 msgid "Password fields must match" @@ -312,7 +394,7 @@ msgstr "" #: InvenTree/views.py:887 templates/navbar.html:95 msgid "System Information" -msgstr "" +msgstr "Información del sistema" #: barcodes/api.py:53 barcodes/api.py:150 msgid "Must provide barcode_data parameter" @@ -376,37 +458,37 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" -msgstr "" +msgstr "Cantidad" #: build/forms.py:49 msgid "Number of items to build" @@ -416,9 +498,9 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" -msgstr "" +msgstr "Números de serie" #: build/forms.py:97 msgid "Enter serial numbers for build outputs" @@ -446,27 +528,28 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" -msgstr "" +msgstr "Unicación" #: build/forms.py:211 msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" -msgstr "" +msgstr "Estado" #: build/forms.py:216 msgid "Build output stock status" @@ -486,7 +569,7 @@ msgstr "" #: build/forms.py:252 msgid "Confirm cancel" -msgstr "" +msgstr "Confirmar cancelación" #: build/forms.py:252 build/views.py:66 msgid "Confirm build cancellation" @@ -517,14 +600,14 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 msgid "Reference" -msgstr "" +msgstr "Referencia" #: build/models.py:137 msgid "Brief description of the build" @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,9 +643,9 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" -msgstr "" +msgstr "Parte" #: build/models.py:160 msgid "Select part to build" @@ -602,7 +685,7 @@ msgstr "" #: build/models.py:198 msgid "Completed items" -msgstr "" +msgstr "Elementos completados" #: build/models.py:200 msgid "Number of stock items which have been completed" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -655,7 +738,7 @@ msgstr "" #: order/templates/order/sales_order_base.html:138 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" -msgstr "" +msgstr "Responsable" #: build/models.py:251 msgid "User responsible for this build order" @@ -667,32 +750,32 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" -msgstr "" +msgstr "Notas" #: build/models.py:262 msgid "Extra build notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,12 +911,12 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" -msgstr "" +msgstr "Número de serie" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -952,17 +1031,17 @@ msgstr "" #: build/templates/build/build_base.html:147 #: build/templates/build/detail.html:64 msgid "Progress" -msgstr "" +msgstr "Progreso" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1105,18 +1184,18 @@ msgstr "" #: build/templates/build/detail.html:46 stock/forms.py:169 stock/forms.py:375 msgid "Destination" -msgstr "" +msgstr "Destinación" #: build/templates/build/detail.html:53 msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" -msgstr "" +msgstr "Lote" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 @@ -1130,7 +1209,7 @@ msgstr "" #: build/templates/build/detail.html:132 templates/js/build.js:756 msgid "Completed" -msgstr "" +msgstr "Completados" #: build/templates/build/detail.html:136 msgid "Build not complete" @@ -1168,8 +1247,9 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" -msgstr "" +msgstr "Detalles" #: build/templates/build/navbar.html:21 build/templates/build/navbar.html:24 #: build/views.py:91 @@ -1202,10 +1282,11 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" -msgstr "" +msgstr "Guardar" #: build/templates/build/unallocate.html:10 msgid "Are you sure you wish to unallocate all stock for this build?" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" -msgstr "" +msgstr "días" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" -msgstr "" +msgstr "Página web" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" -msgstr "" +msgstr "Teléfono" + +#: company/models.py:112 +msgid "Contact phone number" +msgstr "Teléfono de contacto" + +#: company/models.py:115 company/templates/company/company_base.html:91 +msgid "Email" +msgstr "Email" #: company/models.py:115 -msgid "Contact phone number" -msgstr "" - -#: company/models.py:118 company/templates/company/company_base.html:91 -msgid "Email" -msgstr "" - -#: company/models.py:118 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" -msgstr "" +msgstr "Contacto" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" -msgstr "" +msgstr "Fabricante" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" -msgstr "" +msgstr "Proveedor" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" -msgstr "" +msgstr "Nota" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2013,7 +2145,7 @@ msgstr "" #: company/templates/company/company_base.html:84 msgid "Phone" -msgstr "" +msgstr "Teléfono" #: company/templates/company/delete.html:7 #, python-format @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,12 +2170,13 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" -msgstr "" +msgstr "Cliente" #: company/templates/company/detail_manufacturer_part.html:11 #: templates/InvenTree/search.html:149 @@ -2067,7 +2199,7 @@ msgstr "" #: part/templates/part/manufacturer.html:22 #: part/templates/part/supplier.html:20 msgid "Options" -msgstr "" +msgstr "Opciones" #: company/templates/company/detail_manufacturer_part.html:33 #: company/templates/company/detail_supplier_part.html:32 @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2117,7 +2249,7 @@ msgstr "" #: part/templates/part/category.html:114 part/templates/part/category.html:128 #: part/templates/part/stock.html:54 stock/templates/stock/location.html:163 msgid "Export" -msgstr "" +msgstr "Exportar" #: company/templates/company/detail_supplier_part.html:11 #: company/templates/company/manufacturer_part_navbar.html:11 @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2234,7 +2366,7 @@ msgstr "" #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 #: stock/views.py:1002 users/models.py:187 msgid "Delete" -msgstr "" +msgstr "Eliminar" #: company/templates/company/manufacturer_part_suppliers.html:48 #: part/templates/part/supplier.html:51 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2386,14 +2518,14 @@ msgstr "" #: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" -msgstr "" +msgstr "Fabricantes" #: company/views.py:77 templates/InvenTree/search.html:336 #: templates/navbar.html:45 msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/fr/LC_MESSAGES/django.po b/InvenTree/locale/fr/LC_MESSAGES/django.po index ae5d861fa2..9f32eeb22f 100644 --- a/InvenTree/locale/fr/LC_MESSAGES/django.po +++ b/InvenTree/locale/fr/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: French\n" "Language: fr_FR\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: fr\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -26,38 +31,38 @@ msgstr "" #: InvenTree/fields.py:44 msgid "Enter date" -msgstr "" +msgstr "Entrer la date" #: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" -msgstr "" +msgstr "Confirmer" #: InvenTree/forms.py:126 msgid "Confirm delete" -msgstr "" +msgstr "Confirmer la suppression" #: InvenTree/forms.py:127 msgid "Confirm item deletion" -msgstr "" +msgstr "Confirmer la suppression de cet élément" #: InvenTree/forms.py:159 templates/registration/login.html:77 msgid "Enter password" -msgstr "" +msgstr "Entrer le mot de passe" #: InvenTree/forms.py:160 msgid "Enter new password" -msgstr "" +msgstr "Entrer le nouveau mot de passe" #: InvenTree/forms.py:167 msgid "Confirm password" -msgstr "" +msgstr "Confirmez le mot de passe" #: InvenTree/forms.py:168 msgid "Confirm new password" -msgstr "" +msgstr "Confirmer le nouveau mot de passe" #: InvenTree/forms.py:203 msgid "Apply Theme" @@ -72,8 +77,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -101,7 +106,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -111,15 +116,15 @@ msgstr "" #: InvenTree/models.py:62 templates/attachment_table.html:16 msgid "Comment" -msgstr "" +msgstr "Commentaire" #: InvenTree/models.py:62 msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "" @@ -127,8 +132,8 @@ msgstr "" msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -136,11 +141,11 @@ msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,35 +159,35 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" -msgstr "" +msgstr "Description" #: InvenTree/models.py:115 msgid "Description (optional)" -msgstr "" +msgstr "Description (facultative)" #: InvenTree/models.py:123 msgid "parent" -msgstr "" +msgstr "parent" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -198,60 +203,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -292,7 +374,7 @@ msgstr "" #: InvenTree/views.py:587 msgid "Delete Item" -msgstr "" +msgstr "Supprimer cet élément" #: InvenTree/views.py:636 msgid "Check box to confirm item deletion" @@ -376,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -416,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -446,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -517,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -667,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1112,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1168,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1202,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2393,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/it/LC_MESSAGES/django.po b/InvenTree/locale/it/LC_MESSAGES/django.po index 69191acc73..20cbccebaa 100644 --- a/InvenTree/locale/it/LC_MESSAGES/django.po +++ b/InvenTree/locale/it/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: Italian\n" "Language: it_IT\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: it\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -72,8 +77,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -101,7 +106,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -117,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "" @@ -127,8 +132,8 @@ msgstr "" msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -136,11 +141,11 @@ msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,7 +159,7 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "" @@ -166,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -198,60 +203,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -376,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -416,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -446,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -517,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -667,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1112,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1168,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1202,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2393,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/ja/LC_MESSAGES/django.po b/InvenTree/locale/ja/LC_MESSAGES/django.po index 23cec9e6fb..fe9b71062e 100644 --- a/InvenTree/locale/ja/LC_MESSAGES/django.po +++ b/InvenTree/locale/ja/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: Japanese\n" "Language: ja_JP\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: ja\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -72,8 +77,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -101,7 +106,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -117,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "" @@ -127,8 +132,8 @@ msgstr "" msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -136,11 +141,11 @@ msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,7 +159,7 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "" @@ -166,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -198,60 +203,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -376,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -416,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -446,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -517,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -667,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1112,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1168,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1202,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2393,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/pl/LC_MESSAGES/django.po b/InvenTree/locale/pl/LC_MESSAGES/django.po index edc3b32d2b..c9c9975b16 100644 --- a/InvenTree/locale/pl/LC_MESSAGES/django.po +++ b/InvenTree/locale/pl/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: Polish\n" "Language: pl_PL\n" @@ -11,136 +11,141 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: pl\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" -msgstr "" +msgstr "Nie znaleziono punktu końcowego API" #: InvenTree/api.py:110 msgid "No action specified" -msgstr "" +msgstr "Nie określono działania" #: InvenTree/api.py:124 msgid "No matching action found" -msgstr "" +msgstr "Nie znaleziono pasującej akcji" #: InvenTree/fields.py:44 msgid "Enter date" -msgstr "" +msgstr "Wprowadź dane" #: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" -msgstr "" +msgstr "Potwierdź" #: InvenTree/forms.py:126 msgid "Confirm delete" -msgstr "" +msgstr "Potwierdź usunięcie" #: InvenTree/forms.py:127 msgid "Confirm item deletion" -msgstr "" +msgstr "Potwierdź usuwanie elementu" #: InvenTree/forms.py:159 templates/registration/login.html:77 msgid "Enter password" -msgstr "" +msgstr "Wprowadź hasło" #: InvenTree/forms.py:160 msgid "Enter new password" -msgstr "" +msgstr "Wprowadź nowe hasło" #: InvenTree/forms.py:167 msgid "Confirm password" -msgstr "" +msgstr "Potwierdź hasło" #: InvenTree/forms.py:168 msgid "Confirm new password" -msgstr "" +msgstr "Potwierdź nowe hasło" #: InvenTree/forms.py:203 msgid "Apply Theme" -msgstr "" +msgstr "Zastosuj motyw" #: InvenTree/forms.py:233 msgid "Select Category" -msgstr "" +msgstr "Wybierz kategorię" #: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" -msgstr "" +msgstr "Powtórzony numer seryjny: {n}" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" -msgstr "" +msgstr "Podano nieprawidłową ilość" #: InvenTree/helpers.py:387 msgid "Empty serial number string" -msgstr "" +msgstr "Pusty ciąg numeru seryjnego" #: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 #: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" -msgstr "" +msgstr "Nieprawidłowa grupa: {g}" #: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" -msgstr "" +msgstr "Powtórzony numer seryjny: {g}" #: InvenTree/helpers.py:453 msgid "No serial numbers found" -msgstr "" +msgstr "Nie znaleziono numerów seryjnych" #: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" -msgstr "" +msgstr "Ilość numerów seryjnych ({s}) musi odpowiadać ilości ({q})" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" -msgstr "" +msgstr "Załącznik" #: InvenTree/models.py:60 msgid "Select file to attach" -msgstr "" +msgstr "Wybierz plik do załączenia" #: InvenTree/models.py:62 templates/attachment_table.html:16 msgid "Comment" -msgstr "" +msgstr "Komentarz" #: InvenTree/models.py:62 msgid "File comment" -msgstr "" +msgstr "Komentarz pliku" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" -msgstr "" +msgstr "Użytkownik" #: InvenTree/models.py:72 msgid "upload date" -msgstr "" +msgstr "data przesłania" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 msgid "Name" -msgstr "" +msgstr "Nazwa" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,37 +159,37 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" -msgstr "" +msgstr "Opis" #: InvenTree/models.py:115 msgid "Description (optional)" -msgstr "" +msgstr "Opis (opcjonalny)" #: InvenTree/models.py:123 msgid "parent" -msgstr "" +msgstr "nadrzędny" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" -msgstr "" +msgstr "Angielski" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" -msgstr "" +msgstr "Francuski" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" -msgstr "" +msgstr "Niemiecki" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" -msgstr "" +msgstr "Polski" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" -msgstr "" +msgstr "Turecki" #: InvenTree/status.py:93 msgid "Background worker check failed" @@ -192,91 +197,168 @@ msgstr "" #: InvenTree/status.py:97 msgid "Email backend not configured" -msgstr "" +msgstr "Nie skonfigurowano backendu e-mail" #: InvenTree/status.py:100 msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" -msgstr "" +msgstr "W toku" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" -msgstr "" +msgstr "Umieszczony" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" -msgstr "" - -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 -msgid "Cancelled" -msgstr "" - -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 -msgid "Lost" -msgstr "" +msgstr "Zakończono" #: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 -msgid "Returned" -msgstr "" +#: InvenTree/status_codes.py:316 +msgid "Cancelled" +msgstr "Anulowano" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 +msgid "Lost" +msgstr "Zagubiono" + +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 +msgid "Returned" +msgstr "Zwrócone" + +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" -msgstr "" - -#: InvenTree/status_codes.py:184 -msgid "OK" -msgstr "" - -#: InvenTree/status_codes.py:185 -msgid "Attention needed" -msgstr "" +msgstr "Wysłane" #: InvenTree/status_codes.py:186 -msgid "Damaged" -msgstr "" +msgid "OK" +msgstr "OK" #: InvenTree/status_codes.py:187 -msgid "Destroyed" -msgstr "" +msgid "Attention needed" +msgstr "Wymaga uwagi" + +#: InvenTree/status_codes.py:188 +msgid "Damaged" +msgstr "Uszkodzone" #: InvenTree/status_codes.py:189 +msgid "Destroyed" +msgstr "Zniszczone" + +#: InvenTree/status_codes.py:191 msgid "Rejected" +msgstr "Odrzucone" + +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" msgstr "" -#: InvenTree/status_codes.py:237 -msgid "Production" +#: InvenTree/status_codes.py:274 +msgid "Stock item created" msgstr "" +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "Lokalizacja zmieniona" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "Podziel element podrzędny" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "Wyślij do klienta" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "Zwrócony od klienta" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 +msgid "Production" +msgstr "Produkcja" + #: InvenTree/validators.py:22 msgid "Not a valid currency code" -msgstr "" +msgstr "Nieprawidłowy kod waluty" #: InvenTree/validators.py:50 msgid "Invalid character in part name" -msgstr "" +msgstr "Błędny znak w nazwie elementu" #: InvenTree/validators.py:63 #, python-brace-format msgid "IPN must match regex pattern {pat}" -msgstr "" +msgstr "IPN musi być zgodny z wyrażeniem regularnym {pat}" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 #, python-brace-format msgid "Illegal character in name ({x})" -msgstr "" +msgstr "Niedozwolony znak w nazwie ({x})" #: InvenTree/validators.py:132 InvenTree/validators.py:148 msgid "Overage value must not be negative" @@ -292,27 +374,27 @@ msgstr "" #: InvenTree/views.py:587 msgid "Delete Item" -msgstr "" +msgstr "Usuń element" #: InvenTree/views.py:636 msgid "Check box to confirm item deletion" -msgstr "" +msgstr "Zaznacz pole aby potwierdzić usunięcie elementu" #: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" -msgstr "" +msgstr "Edytuj informacje użytkownika" #: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 msgid "Set Password" -msgstr "" +msgstr "Ustaw hasło" #: InvenTree/views.py:681 msgid "Password fields must match" -msgstr "" +msgstr "Hasła muszą być zgodne" #: InvenTree/views.py:887 templates/navbar.html:95 msgid "System Information" -msgstr "" +msgstr "Informacja systemowa" #: barcodes/api.py:53 barcodes/api.py:150 msgid "Must provide barcode_data parameter" @@ -356,7 +438,7 @@ msgstr "" #: build/forms.py:37 msgid "Build Order reference" -msgstr "" +msgstr "Numer Zlecenia Budowy" #: build/forms.py:38 msgid "Order target date" @@ -370,43 +452,43 @@ msgstr "" #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 msgid "Target Date" -msgstr "" +msgstr "Data docelowa" #: build/forms.py:43 build/models.py:224 msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" -msgstr "" +msgstr "Ilość" #: build/forms.py:49 msgid "Number of items to build" @@ -416,9 +498,9 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" -msgstr "" +msgstr "Numer seryjny" #: build/forms.py:97 msgid "Enter serial numbers for build outputs" @@ -438,35 +520,36 @@ msgstr "" #: build/forms.py:169 msgid "Confirm stock allocation" -msgstr "" +msgstr "Potwierdź przydział zapasów" #: build/forms.py:186 msgid "Mark build as complete" -msgstr "" +msgstr "Oznacz budowę jako ukończoną" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" -msgstr "" +msgstr "Lokalizacja" #: build/forms.py:211 msgid "Location of completed parts" -msgstr "" +msgstr "Lokalizacja ukończonych części" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" -msgstr "" +msgstr "Status" #: build/forms.py:216 msgid "Build output stock status" @@ -474,7 +557,7 @@ msgstr "" #: build/forms.py:223 msgid "Confirm incomplete" -msgstr "" +msgstr "Potwierdź nieukończone" #: build/forms.py:224 msgid "Confirm completion with incomplete stock allocation" @@ -486,7 +569,7 @@ msgstr "" #: build/forms.py:252 msgid "Confirm cancel" -msgstr "" +msgstr "Na pewno anulować?" #: build/forms.py:252 build/views.py:66 msgid "Confirm build cancellation" @@ -501,7 +584,7 @@ msgstr "" #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" -msgstr "" +msgstr "Zlecenie Budowy" #: build/models.py:66 build/templates/build/index.html:8 #: build/templates/build/index.html:15 order/templates/order/so_builds.html:12 @@ -511,46 +594,46 @@ msgstr "" #: templates/InvenTree/search.html:185 #: templates/InvenTree/settings/tabs.html:31 users/models.py:43 msgid "Build Orders" -msgstr "" +msgstr "Zlecenia budowy" #: build/models.py:126 msgid "Build Order Reference" -msgstr "" +msgstr "Odwołanie do zamówienia wykonania" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 msgid "Reference" -msgstr "" +msgstr "Referencja" #: build/models.py:137 msgid "Brief description of the build" -msgstr "" +msgstr "Krótki opis budowy" #: build/models.py:146 build/templates/build/build_base.html:153 #: build/templates/build/detail.html:77 msgid "Parent Build" -msgstr "" +msgstr "Budowa nadrzędna" #: build/models.py:147 msgid "BuildOrder to which this build is allocated" -msgstr "" +msgstr "Zamówienie budowy, do którego budowa jest przypisana" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,94 +643,94 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" -msgstr "" +msgstr "Część" #: build/models.py:160 msgid "Select part to build" -msgstr "" +msgstr "Wybierz część do budowy" #: build/models.py:165 msgid "Sales Order Reference" -msgstr "" +msgstr "Odwołanie do zamówienia sprzedaży" #: build/models.py:169 msgid "SalesOrder to which this build is allocated" -msgstr "" +msgstr "Zamówienie sprzedaży, do którego budowa jest przypisana" #: build/models.py:174 msgid "Source Location" -msgstr "" +msgstr "Lokalizacja źródła" #: build/models.py:178 msgid "Select location to take stock from for this build (leave blank to take from any stock location)" -msgstr "" +msgstr "Wybierz lokalizację, z której pobrać element do budowy (pozostaw puste, aby wziąć z dowolnej lokalizacji)" #: build/models.py:183 msgid "Destination Location" -msgstr "" +msgstr "Lokalizacja docelowa" #: build/models.py:187 msgid "Select location where the completed items will be stored" -msgstr "" +msgstr "Wybierz lokalizację, w której będą przechowywane ukończone elementy" #: build/models.py:191 msgid "Build Quantity" -msgstr "" +msgstr "Ilość do stworzenia" #: build/models.py:194 msgid "Number of stock items to build" -msgstr "" +msgstr "Ilość przedmiotów do zbudowania" #: build/models.py:198 msgid "Completed items" -msgstr "" +msgstr "Ukończone elementy" #: build/models.py:200 msgid "Number of stock items which have been completed" -msgstr "" +msgstr "Ilość produktów magazynowych które zostały ukończone" #: build/models.py:204 part/templates/part/part_base.html:160 msgid "Build Status" -msgstr "" +msgstr "Status budowania" #: build/models.py:208 msgid "Build status code" -msgstr "" +msgstr "Kod statusu budowania" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" -msgstr "" +msgstr "Kod partii" #: build/models.py:216 msgid "Batch code for this build output" -msgstr "" +msgstr "Kod partii dla wyjścia budowy" #: build/models.py:219 order/models.py:105 part/models.py:882 #: part/templates/part/detail.html:126 templates/js/order.js:293 msgid "Creation Date" -msgstr "" +msgstr "Data utworzenia" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" -msgstr "" +msgstr "Docelowy termin zakończenia" #: build/models.py:227 order/models.py:218 templates/js/build.js:788 msgid "Completion Date" -msgstr "" +msgstr "Data zakończenia" #: build/models.py:233 msgid "completed by" -msgstr "" +msgstr "zrealizowane przez" #: build/models.py:241 msgid "Issued by" -msgstr "" +msgstr "Wydany przez" #: build/models.py:242 msgid "User who issued this build order" -msgstr "" +msgstr "Użytkownik, który wydał to zamówienie" #: build/models.py:250 build/templates/build/build_base.html:174 #: build/templates/build/detail.html:105 order/models.py:119 @@ -655,11 +738,11 @@ msgstr "" #: order/templates/order/sales_order_base.html:138 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" -msgstr "" +msgstr "Odpowiedzialny" #: build/models.py:251 msgid "User responsible for this build order" -msgstr "" +msgstr "Użytkownik odpowiedzialny za to zamówienie budowy" #: build/models.py:256 build/templates/build/detail.html:91 #: company/templates/company/manufacturer_part_base.html:79 @@ -667,155 +750,151 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" -msgstr "" +msgstr "Link Zewnętrzny" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" -msgstr "" +msgstr "Link do zewnętrznego adresu URL" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" -msgstr "" +msgstr "Uwagi" #: build/models.py:262 msgid "Extra build notes" -msgstr "" +msgstr "Dodatkowe notatki do budowy" #: build/models.py:739 msgid "No build output specified" -msgstr "" +msgstr "Nie określono danych wyjściowych budowy" #: build/models.py:742 msgid "Build output is already completed" -msgstr "" +msgstr "Budowanie wyjścia jest już ukończone" #: build/models.py:745 msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" -msgstr "" +msgstr "Budowa" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" -msgstr "" +msgstr "Element magazynowy" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" -msgstr "" +msgstr "Lokalizacja magazynowania przedmiotu" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" -msgstr "" +msgstr "Zainstaluj do" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" -msgstr "" +msgstr "Docelowa lokalizacja magazynowa przedmiotu" #: build/templates/build/allocate.html:7 msgid "Allocate Parts" -msgstr "" +msgstr "Przydziel części" #: build/templates/build/allocate.html:15 msgid "Allocate Stock to Build" -msgstr "" +msgstr "Przydziel zapasy do budowy" #: build/templates/build/allocate.html:22 msgid "Allocate stock to build" -msgstr "" +msgstr "Przydziel zapasy do budowy" #: build/templates/build/allocate.html:23 msgid "Auto Allocate" -msgstr "" +msgstr "Automatyczne przypisywanie" #: build/templates/build/allocate.html:25 templates/js/build.js:646 msgid "Unallocate stock" -msgstr "" +msgstr "Cofnij przydział zapasów" #: build/templates/build/allocate.html:26 build/views.py:319 build/views.py:805 msgid "Unallocate Stock" -msgstr "" +msgstr "Cofnij przydział zapasów" #: build/templates/build/allocate.html:29 msgid "Order required parts" -msgstr "" +msgstr "Zamów wymagane komponenty" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" -msgstr "" +msgstr "Zamów części" #: build/templates/build/allocate.html:36 msgid "Untracked stock has been fully allocated for this Build Order" @@ -832,12 +911,12 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" -msgstr "" +msgstr "Numer Seryjny" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 @@ -846,11 +925,11 @@ msgstr "" #: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" -msgstr "" +msgstr "Załączniki" #: build/templates/build/auto_allocate.html:9 msgid "Automatically Allocate Stock" -msgstr "" +msgstr "Przydziel automatycznie zapasy" #: build/templates/build/auto_allocate.html:10 msgid "The following stock items will be allocated to the specified build output" @@ -897,10 +976,10 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" -msgstr "" +msgstr "Widok administratora" #: build/templates/build/build_base.html:71 #: build/templates/build/build_base.html:140 @@ -908,18 +987,18 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" -msgstr "" +msgstr "Zaległe" #: build/templates/build/build_base.html:80 msgid "Print actions" -msgstr "" +msgstr "Akcje druku" #: build/templates/build/build_base.html:84 msgid "Print Build Order" -msgstr "" +msgstr "Wydrukuj Numer Zlecenia Budowy" #: build/templates/build/build_base.html:90 #: build/templates/build/build_base.html:215 @@ -932,17 +1011,17 @@ msgstr "" #: build/templates/build/build_base.html:99 msgid "Edit Build" -msgstr "" +msgstr "Edytuj Budowę" #: build/templates/build/build_base.html:101 #: build/templates/build/build_base.html:199 build/views.py:57 msgid "Cancel Build" -msgstr "" +msgstr "Anuluj Budowę" #: build/templates/build/build_base.html:114 #: build/templates/build/detail.html:11 msgid "Build Details" -msgstr "" +msgstr "Szczegóły budowy" #: build/templates/build/build_base.html:140 #, python-format @@ -952,25 +1031,25 @@ msgstr "" #: build/templates/build/build_base.html:147 #: build/templates/build/detail.html:64 msgid "Progress" -msgstr "" +msgstr "Postęp" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" -msgstr "" +msgstr "Zamówienie zakupu" #: build/templates/build/build_base.html:167 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" -msgstr "" +msgstr "Dodane przez" #: build/templates/build/build_base.html:207 msgid "Incomplete Outputs" @@ -995,7 +1074,7 @@ msgstr "" #: build/templates/build/build_output.html:23 msgid "Create New Output" -msgstr "" +msgstr "Utwórz nowe wyjście" #: build/templates/build/build_output.html:36 msgid "Create a new build output" @@ -1035,7 +1114,7 @@ msgstr "" #: build/templates/build/cancel.html:5 msgid "Are you sure you wish to cancel this build?" -msgstr "" +msgstr "Czy na pewno przerwać tę budowę?" #: build/templates/build/complete.html:8 msgid "Build Order is complete" @@ -1085,11 +1164,11 @@ msgstr "" #: build/templates/build/create_build_item.html:17 #, python-format msgid "No stock available for %(part)s" -msgstr "" +msgstr "Brak zapasów dla %(part)s" #: build/templates/build/delete_build_item.html:8 msgid "Are you sure you want to unallocate this stock?" -msgstr "" +msgstr "Czy na pewno chcesz anulować przydział tego zapasu?" #: build/templates/build/delete_build_item.html:11 msgid "The selected stock will be unallocated from the build output" @@ -1097,7 +1176,7 @@ msgstr "" #: build/templates/build/detail.html:35 msgid "Stock Source" -msgstr "" +msgstr "Źródło magazynu" #: build/templates/build/detail.html:40 msgid "Stock can be taken from any available location." @@ -1105,24 +1184,24 @@ msgstr "" #: build/templates/build/detail.html:46 stock/forms.py:169 stock/forms.py:375 msgid "Destination" -msgstr "" +msgstr "Przeznaczenie" #: build/templates/build/detail.html:53 msgid "Destination location not specified" -msgstr "" +msgstr "Nie określono lokalizacji docelowej" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" -msgstr "" +msgstr "Partia" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 #: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 msgid "Created" -msgstr "" +msgstr "Utworzony" #: build/templates/build/detail.html:127 msgid "No target date set" @@ -1130,11 +1209,11 @@ msgstr "" #: build/templates/build/detail.html:132 templates/js/build.js:756 msgid "Completed" -msgstr "" +msgstr "Zakończone" #: build/templates/build/detail.html:136 msgid "Build not complete" -msgstr "" +msgstr "Budowa niezakończona" #: build/templates/build/edit_build_item.html:7 msgid "Alter the quantity of stock allocated to the build output" @@ -1142,39 +1221,40 @@ msgstr "" #: build/templates/build/index.html:28 build/views.py:678 msgid "New Build Order" -msgstr "" +msgstr "Nowe zlecenie budowy" #: build/templates/build/index.html:37 build/templates/build/index.html:38 msgid "Print Build Orders" -msgstr "" +msgstr "Wydrukuj zlecenia budowy" #: build/templates/build/index.html:43 #: order/templates/order/purchase_orders.html:27 #: order/templates/order/sales_orders.html:27 msgid "Display calendar view" -msgstr "" +msgstr "Pokaż widok kalendarza" #: build/templates/build/index.html:46 #: order/templates/order/purchase_orders.html:30 #: order/templates/order/sales_orders.html:30 msgid "Display list view" -msgstr "" +msgstr "Pokaż widok listy" #: build/templates/build/navbar.html:12 msgid "Build Order Details" -msgstr "" +msgstr "Szczegóły zlecenia budowy" #: build/templates/build/navbar.html:15 #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" -msgstr "" +msgstr "Szczegóły" #: build/templates/build/navbar.html:21 build/templates/build/navbar.html:24 #: build/views.py:91 msgid "Allocate Stock" -msgstr "" +msgstr "Przydziel zapasy" #: build/templates/build/navbar.html:29 build/templates/build/navbar.html:32 msgid "Build Outputs" @@ -1182,34 +1262,35 @@ msgstr "" #: build/templates/build/navbar.html:39 msgid "Child Builds" -msgstr "" +msgstr "Budowy podrzędne" #: build/templates/build/navbar.html:50 msgid "Build Order Notes" -msgstr "" +msgstr "Notatki zlecenia budowy" #: build/templates/build/notes.html:12 msgid "Build Notes" -msgstr "" +msgstr "Notatki tworzenia" #: build/templates/build/notes.html:14 company/templates/company/notes.html:13 #: order/templates/order/order_notes.html:15 #: order/templates/order/sales_order_notes.html:16 #: part/templates/part/notes.html:14 stock/templates/stock/item_notes.html:15 msgid "Edit notes" -msgstr "" +msgstr "Edytuj uwagi" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" -msgstr "" +msgstr "Zapisz" #: build/templates/build/unallocate.html:10 msgid "Are you sure you wish to unallocate all stock for this build?" -msgstr "" +msgstr "Czy na pewno chcesz cofnąć przydział wszystkich zapasów dla tej budowy?" #: build/templates/build/unallocate.html:12 msgid "All incomplete stock allocations will be removed from the build" @@ -1217,7 +1298,7 @@ msgstr "" #: build/views.py:77 msgid "Build was cancelled" -msgstr "" +msgstr "Tworzenie zostało przerwane" #: build/views.py:138 msgid "Allocated stock to build output" @@ -1225,15 +1306,15 @@ msgstr "" #: build/views.py:150 msgid "Create Build Output" -msgstr "" +msgstr "Utwórz zlecenie budowy" #: build/views.py:168 msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" -msgstr "" +msgstr "Numer seryjny już istnieje" #: build/views.py:193 msgid "Serial numbers required for trackable build output" @@ -1297,7 +1378,7 @@ msgstr "" #: build/views.py:732 msgid "Created new build" -msgstr "" +msgstr "Utworzona nowa budowa" #: build/views.py:753 msgid "Edit Build Order Details" @@ -1330,7 +1411,7 @@ msgstr "" #: build/views.py:872 templates/js/bom.js:230 templates/js/build.js:575 #: templates/js/build.js:838 templates/js/build.js:1021 msgid "Available" -msgstr "" +msgstr "Dostępne" #: build/views.py:874 msgid "Stock item must be selected" @@ -1348,626 +1429,677 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" -msgstr "" +msgstr "Dodano załącznik" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" -msgstr "" +msgstr "Edytuj załącznik" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" -msgstr "" +msgstr "Załącznik zaktualizowany" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" -msgstr "" +msgstr "Usuń załącznik" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" +msgstr "Załącznik usunięto" + +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "Nazwa instancji InvenTree" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" -msgstr "" +msgstr "Nazwa firmy" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" -msgstr "" +msgstr "Bazowy URL" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" -msgstr "" +msgstr "Bazowy adres URL dla instancji serwera" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" -msgstr "" +msgstr "Domyślna waluta" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" -msgstr "" +msgstr "Domyślna waluta" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" -msgstr "" +msgstr "Pobierz z adresu URL" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" -msgstr "" +msgstr "Zezwól na pobieranie zewnętrznych obrazów i plików z zewnętrznego URL" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" -msgstr "" +msgstr "Obsługa kodu kreskowego" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" -msgstr "" +msgstr "Włącz obsługę skanera kodów" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" -msgstr "" +msgstr "Wyrażenie regularne IPN" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" -msgstr "" +msgstr "Zezwól na powtarzający się IPN" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" -msgstr "" +msgstr "Zezwól na edycję IPN" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" -msgstr "" +msgstr "Skopiuj BOM komponentu" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" -msgstr "" +msgstr "Szablon" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" -msgstr "" +msgstr "Złożenie" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" -msgstr "" +msgstr "Komponent" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" -msgstr "" +msgstr "Możliwość zakupu" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" -msgstr "" +msgstr "Części są domyślnie z możliwością zakupu" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" -msgstr "" +msgstr "Możliwość sprzedaży" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" -msgstr "" +msgstr "Części są domyślnie z możliwością sprzedaży" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" -msgstr "" +msgstr "Możliwość śledzenia" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" -msgstr "" +msgstr "Części są domyślnie z możliwością śledzenia" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" -msgstr "" +msgstr "Wirtualny" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" -msgstr "" +msgstr "Części są domyślnie wirtualne" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" -msgstr "" +msgstr "Tryb Debugowania" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" -msgstr "" +msgstr "Rozmiar strony" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" -msgstr "" +msgstr "Raporty testów" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" -msgstr "" +msgstr "Włącz generowanie raportów testów" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" -msgstr "" +msgstr "dni" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" -msgstr "" +msgstr "Grupuj według komponentu" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" -msgstr "" +msgstr "Ustawienia wartości" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" -msgstr "" +msgstr "Cena" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" -msgstr "" +msgstr "Domyślny" #: common/templates/common/edit_setting.html:11 msgid "Current value" -msgstr "" +msgstr "Aktualna wartość" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" -msgstr "" +msgstr "Zmień ustawienie" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 -#: company/templates/company/detail.html:42 -msgid "Currency" +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "Wyślik plik" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 +#: company/templates/company/detail.html:42 +msgid "Currency" +msgstr "Waluta" + +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" #: company/forms.py:77 part/forms.py:46 msgid "URL" -msgstr "" +msgstr "URL" #: company/forms.py:78 part/forms.py:47 msgid "Image URL" -msgstr "" +msgstr "URL zdjęcia" #: company/forms.py:118 msgid "Single Price" -msgstr "" +msgstr "Cena jednostkowa" #: company/forms.py:120 msgid "Single quantity price" -msgstr "" +msgstr "Cena jednostkowa" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" -msgstr "" +msgstr "Wybierz producenta" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" -msgstr "" +msgstr "Numer producenta" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" -msgstr "" +msgstr "MPN" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" -msgstr "" +msgstr "Opis firmy" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" -msgstr "" +msgstr "Opis firmy" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" -msgstr "" +msgstr "Strona WWW" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" -msgstr "" +msgstr "Witryna internetowa firmy" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" -msgstr "" +msgstr "Adres" + +#: company/models.py:108 +msgid "Company address" +msgstr "Adres firmy" #: company/models.py:111 -msgid "Company address" -msgstr "" - -#: company/models.py:114 msgid "Phone number" -msgstr "" +msgstr "Numer telefonu" + +#: company/models.py:112 +msgid "Contact phone number" +msgstr "Numer telefonu kontaktowego" + +#: company/models.py:115 company/templates/company/company_base.html:91 +msgid "Email" +msgstr "Adres E-Mail" #: company/models.py:115 -msgid "Contact phone number" -msgstr "" - -#: company/models.py:118 company/templates/company/company_base.html:91 -msgid "Email" -msgstr "" - -#: company/models.py:118 msgid "Contact email address" -msgstr "" +msgstr "Kontaktowy adres e-mail" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" -msgstr "" +msgstr "Kontakt" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" -msgstr "" +msgstr "Punkt kontaktowy" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" -msgstr "" +msgstr "Łącze" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" -msgstr "" +msgstr "Link do informacji o zewnętrznym przedsiębiorstwie" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" -msgstr "" +msgstr "Obraz" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" -msgstr "" +msgstr "jest klientem" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" -msgstr "" +msgstr "Czy sprzedajesz produkty tej firmie?" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" -msgstr "" +msgstr "jest dostawcą" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" -msgstr "" +msgstr "Czy kupujesz przedmioty od tej firmy?" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" -msgstr "" +msgstr "jest producentem" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" -msgstr "" +msgstr "Czy to przedsiębiorstwo produkuje części?" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" -msgstr "" +msgstr "Część bazowa" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" -msgstr "" +msgstr "Wybierz część" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" -msgstr "" +msgstr "Producent" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" -msgstr "" +msgstr "Dostawca" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" -msgstr "" +msgstr "Wybierz dostawcę" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" -msgstr "" +msgstr "SKU" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" -msgstr "" +msgstr "Część producenta" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" -msgstr "" +msgstr "Uwaga" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" -msgstr "" +msgstr "koszt podstawowy" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" -msgstr "" +msgstr "Opakowanie" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" -msgstr "" +msgstr "Opakowanie części" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" -msgstr "" +msgstr "wielokrotność" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1981,19 +2113,19 @@ msgstr "" #: company/templates/company/company_base.html:35 #: templates/InvenTree/search.html:304 templates/js/company.js:33 msgid "Company" -msgstr "" +msgstr "Firma" #: company/templates/company/company_base.html:25 #: part/templates/part/part_thumb.html:21 msgid "Upload new image" -msgstr "" +msgstr "Prześlij nowy obraz" #: company/templates/company/company_base.html:27 #: part/templates/part/part_thumb.html:23 msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2013,7 +2145,7 @@ msgstr "" #: company/templates/company/company_base.html:84 msgid "Phone" -msgstr "" +msgstr "Telefon" #: company/templates/company/delete.html:7 #, python-format @@ -2022,43 +2154,43 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" #: company/templates/company/detail.html:21 msgid "Company Name" -msgstr "" +msgstr "Nazwa firmy" #: company/templates/company/detail.html:36 msgid "No website specified" -msgstr "" +msgstr "Nie określono strony internetowej" #: company/templates/company/detail.html:45 msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" -msgstr "" +msgstr "Klient" #: company/templates/company/detail_manufacturer_part.html:11 #: templates/InvenTree/search.html:149 msgid "Manufacturer Parts" -msgstr "" +msgstr "Części producenta" #: company/templates/company/detail_manufacturer_part.html:22 msgid "Create new manufacturer part" -msgstr "" +msgstr "Utwórz nową część producenta" #: company/templates/company/detail_manufacturer_part.html:23 #: part/templates/part/manufacturer.html:19 msgid "New Manufacturer Part" -msgstr "" +msgstr "Nowa część producenta" #: company/templates/company/detail_manufacturer_part.html:28 #: company/templates/company/detail_supplier_part.html:27 @@ -2067,120 +2199,120 @@ msgstr "" #: part/templates/part/manufacturer.html:22 #: part/templates/part/supplier.html:20 msgid "Options" -msgstr "" +msgstr "Opcje" #: company/templates/company/detail_manufacturer_part.html:33 #: company/templates/company/detail_supplier_part.html:32 #: part/templates/part/category.html:127 msgid "Order parts" -msgstr "" +msgstr "Zamów części" #: company/templates/company/detail_manufacturer_part.html:36 #: company/templates/company/detail_supplier_part.html:35 msgid "Delete parts" -msgstr "" +msgstr "Usuń części" #: company/templates/company/detail_manufacturer_part.html:36 #: company/templates/company/detail_supplier_part.html:35 msgid "Delete Parts" -msgstr "" +msgstr "Usuń części" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" -msgstr "" +msgstr "Nowy komponent" #: company/templates/company/detail_manufacturer_part.html:67 #: company/templates/company/detail_supplier_part.html:67 msgid "Create new Part" -msgstr "" +msgstr "Utwórz nowy komponent" #: company/templates/company/detail_manufacturer_part.html:72 #: company/views.py:71 part/templates/part/manufacturer.html:52 #: part/templates/part/supplier.html:56 msgid "New Manufacturer" -msgstr "" +msgstr "Now producent" #: company/templates/company/detail_manufacturer_part.html:73 #: company/views.py:284 msgid "Create new Manufacturer" -msgstr "" +msgstr "Utwórz nowego producenta" #: company/templates/company/detail_stock.html:10 msgid "Supplier Stock" -msgstr "" +msgstr "Zapasy dostawcy" #: company/templates/company/detail_stock.html:37 #: company/templates/company/supplier_part_stock.html:34 #: part/templates/part/category.html:114 part/templates/part/category.html:128 #: part/templates/part/stock.html:54 stock/templates/stock/location.html:163 msgid "Export" -msgstr "" +msgstr "Eksportuj" #: company/templates/company/detail_supplier_part.html:11 #: company/templates/company/manufacturer_part_navbar.html:11 #: company/templates/company/manufacturer_part_suppliers.html:10 #: templates/InvenTree/search.html:164 msgid "Supplier Parts" -msgstr "" +msgstr "Komponenty dostawcy" #: company/templates/company/detail_supplier_part.html:21 #: order/templates/order/order_wizard/select_parts.html:42 #: order/templates/order/purchase_order_detail.html:50 msgid "Create new supplier part" -msgstr "" +msgstr "Utwórz nowego dostawcę części" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" -msgstr "" +msgstr "Now dostawca części" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" -msgstr "" +msgstr "Nowy dostawca" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" -msgstr "" +msgstr "Dodaj nowego dostawcę" #: company/templates/company/index.html:8 msgid "Supplier List" -msgstr "" +msgstr "Lista dostawców" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 #: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 msgid "Order part" -msgstr "" +msgstr "Zamów część" #: company/templates/company/manufacturer_part_base.html:41 msgid "Edit manufacturer part" -msgstr "" +msgstr "Edytuj część producenta" #: company/templates/company/manufacturer_part_base.html:45 msgid "Delete manufacturer part" -msgstr "" +msgstr "Usuń cześć producenta" #: company/templates/company/manufacturer_part_base.html:57 #: company/templates/company/manufacturer_part_detail.html:10 msgid "Manufacturer Part Details" -msgstr "" +msgstr "Szczegóły części producenta" #: company/templates/company/manufacturer_part_base.html:62 #: company/templates/company/manufacturer_part_detail.html:18 #: company/templates/company/supplier_part_base.html:61 #: company/templates/company/supplier_part_detail.html:18 msgid "Internal Part" -msgstr "" +msgstr "Część wewnętrzna" #: company/templates/company/manufacturer_part_delete.html:6 msgid "Are you sure you want to delete the following Manufacturer Parts?" @@ -2196,7 +2328,7 @@ msgstr "" #: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" -msgstr "" +msgstr "Dostawcy" #: company/templates/company/manufacturer_part_navbar.html:19 msgid "Manufacturer Part Stock" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2213,7 +2345,7 @@ msgstr "" #: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" -msgstr "" +msgstr "Stan" #: company/templates/company/manufacturer_part_navbar.html:26 msgid "Manufacturer Part Orders" @@ -2222,7 +2354,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:29 #: company/templates/company/supplier_part_navbar.html:22 msgid "Orders" -msgstr "" +msgstr "Zamówienia" #: company/templates/company/manufacturer_part_suppliers.html:22 #: part/templates/part/supplier.html:22 @@ -2234,12 +2366,12 @@ msgstr "" #: part/templates/part/related.html:44 part/templates/part/supplier.html:22 #: stock/views.py:1002 users/models.py:187 msgid "Delete" -msgstr "" +msgstr "Usuń" #: company/templates/company/manufacturer_part_suppliers.html:48 #: part/templates/part/supplier.html:51 msgid "Create new supplier" -msgstr "" +msgstr "Utwórz nowego dostawcę" #: company/templates/company/navbar.html:20 #: company/templates/company/navbar.html:23 @@ -2249,7 +2381,7 @@ msgstr "" #: company/templates/company/navbar.html:29 #: company/templates/company/navbar.html:32 msgid "Supplied Parts" -msgstr "" +msgstr "Dostarczone części" #: company/templates/company/navbar.html:38 part/templates/part/navbar.html:33 #: stock/templates/stock/location.html:107 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2351,7 +2483,7 @@ msgstr "" #: company/templates/company/supplier_part_navbar.html:29 msgid "Pricing" -msgstr "" +msgstr "Cennik" #: company/templates/company/supplier_part_orders.html:18 #: part/templates/part/orders.html:18 @@ -2360,10 +2492,10 @@ msgstr "" #: company/templates/company/supplier_part_pricing.html:11 msgid "Pricing Information" -msgstr "" +msgstr "Informacja cenowa" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2375,7 +2507,7 @@ msgstr "" #: company/templates/company/supplier_part_pricing.html:89 #: part/templates/part/sale_prices.html:97 msgid "Edit price break" -msgstr "" +msgstr "Edytuj przedział cenowy" #: company/templates/company/supplier_part_pricing.html:90 #: part/templates/part/sale_prices.html:98 @@ -2386,33 +2518,38 @@ msgstr "" #: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" -msgstr "" +msgstr "Producenci" #: company/views.py:77 templates/InvenTree/search.html:336 #: templates/navbar.html:45 msgid "Customers" -msgstr "" +msgstr "Klienci" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" -msgstr "" +msgstr "Nowy klient" #: company/views.py:86 msgid "Companies" -msgstr "" +msgstr "Firmy" #: company/views.py:87 msgid "New Company" -msgstr "" +msgstr "Nowa firma" #: company/views.py:169 part/views.py:848 msgid "Download Image" -msgstr "" +msgstr "Pobierz obraz" #: company/views.py:198 part/views.py:880 msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2427,27 +2564,27 @@ msgstr "" #: company/views.py:259 msgid "Edit Company" -msgstr "" +msgstr "Edytuj firmę" #: company/views.py:264 msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" -msgstr "" +msgstr "Utwórz nowego klienta" #: company/views.py:289 msgid "Create new Company" -msgstr "" +msgstr "Utwórz nową firmę" #: company/views.py:316 msgid "Created new company" -msgstr "" +msgstr "Utwórz nową firmę" #: company/views.py:332 msgid "Company was deleted" -msgstr "" +msgstr "Usunięto firmę" #: company/views.py:357 msgid "Edit Manufacturer Part" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" -msgstr "" +msgstr "Edytuj przedział cenowy" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,71 +2626,79 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" -msgstr "" +msgstr "Nazwa etykiety" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" -msgstr "" +msgstr "Opis etykiety" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" -msgstr "" +msgstr "Etykieta" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" -msgstr "" +msgstr "Aktywne" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 -msgid "Width [mm]" -msgstr "" - #: label/models.py:130 +msgid "Width [mm]" +msgstr "Szerokość [mm]" + +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 -msgid "Height [mm]" -msgstr "" - #: label/models.py:137 +msgid "Height [mm]" +msgstr "Wysokość [mm]" + +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" -msgstr "" +msgstr "Filtry" #: order/forms.py:27 order/templates/order/order_base.html:47 msgid "Place order" -msgstr "" +msgstr "Złóż zamówienie" #: order/forms.py:38 order/templates/order/order_base.html:54 msgid "Mark order as complete" -msgstr "" +msgstr "Oznacz zamówienie jako zakończone" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 #: order/templates/order/sales_order_base.html:59 msgid "Cancel order" -msgstr "" +msgstr "Anuluj zamówienie" #: order/forms.py:71 order/templates/order/sales_order_base.html:56 msgid "Ship order" -msgstr "" +msgstr "Wyślij zamówienie" #: order/forms.py:82 msgid "Receive parts to this location" @@ -2571,43 +2716,43 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" -msgstr "" +msgstr "Wprowadź ilość produktów magazynowych" #: order/models.py:99 msgid "Order reference" -msgstr "" +msgstr "Odniesienie zamówienia" #: order/models.py:101 msgid "Order description" -msgstr "" +msgstr "Opis Zamówienia" #: order/models.py:103 msgid "Link to external page" -msgstr "" +msgstr "Link do zewnętrznej witryny" #: order/models.py:111 part/templates/part/detail.html:132 msgid "Created By" -msgstr "" +msgstr "Utworzony przez" #: order/models.py:118 msgid "User or group responsible for this order" -msgstr "" +msgstr "Użytkownik lub grupa odpowiedzialna za to zamówienie" #: order/models.py:123 msgid "Order notes" -msgstr "" +msgstr "Notatki do zamówienia" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2626,11 +2771,11 @@ msgstr "" #: order/models.py:201 msgid "received by" -msgstr "" +msgstr "odebrane przez" #: order/models.py:206 msgid "Issue Date" -msgstr "" +msgstr "Data wydania" #: order/models.py:207 msgid "Date order was issued" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" -msgstr "" +msgstr "Data wysyłki" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" -msgstr "" +msgstr "wysłane przez" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" -msgstr "" +msgstr "Ilość elementów" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" -msgstr "" +msgstr "Zamówienie" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" -msgstr "" +msgstr "Odebrane" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" -msgstr "" +msgstr "Cena zakupu" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" -msgstr "" +msgstr "Cena zakupu jednostkowego" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "Cena sprzedaży" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "Jednostkowa cena sprzedaży" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" -msgstr "" +msgstr "Linia" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" -msgstr "" +msgstr "Komponent" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2819,20 +2970,20 @@ msgstr "" #: order/templates/order/order_base.html:82 #: order/templates/order/sales_order_base.html:82 msgid "Order Status" -msgstr "" +msgstr "Status zamówienia" #: order/templates/order/order_base.html:117 #: report/templates/report/inventree_build_order_base.html:122 msgid "Issued" -msgstr "" +msgstr "Wydany" #: order/templates/order/order_base.html:180 #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" -msgstr "" +msgstr "Nowa lokalizacja" #: order/templates/order/order_base.html:181 #: order/templates/order/purchase_order_detail.html:101 @@ -2862,6 +3013,75 @@ msgstr "" #: order/templates/order/order_notes.html:13 msgid "Order Notes" +msgstr "Notatki zamówień" + +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "Wiersz" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." msgstr "" #: order/templates/order/order_wizard/select_parts.html:9 @@ -2878,7 +3098,7 @@ msgstr "" #: order/templates/order/order_wizard/select_parts.html:31 msgid "Select Supplier" -msgstr "" +msgstr "Wybierz dostawcę" #: order/templates/order/order_wizard/select_parts.html:57 #, python-format @@ -2888,7 +3108,7 @@ msgstr "" #: order/templates/order/order_wizard/select_parts.html:69 #: part/templates/part/set_category.html:32 msgid "Remove part" -msgstr "" +msgstr "Usuń część" #: order/templates/order/order_wizard/select_pos.html:8 msgid "Step 2 of 2 - Select Purchase Orders" @@ -2901,7 +3121,7 @@ msgstr "" #: order/templates/order/order_wizard/select_pos.html:31 #: templates/js/order.js:205 templates/js/order.js:308 msgid "Items" -msgstr "" +msgstr "Przedmioty" #: order/templates/order/order_wizard/select_pos.html:32 msgid "Select Purchase Order" @@ -2929,15 +3149,15 @@ msgstr "" #: order/templates/order/po_navbar.html:20 #: order/templates/order/po_received_items.html:12 msgid "Received Items" -msgstr "" +msgstr "Otrzymane elementy" #: order/templates/order/purchase_order_detail.html:14 msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" -msgstr "" +msgstr "Cena jednostkowa" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,10 +3201,10 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" -msgstr "" +msgstr "Części" #: order/templates/order/receive_parts.html:15 msgid "Select parts to receive against this order" @@ -2991,7 +3212,7 @@ msgstr "" #: order/templates/order/receive_parts.html:20 msgid "Order Code" -msgstr "" +msgstr "Kod zamówienia" #: order/templates/order/receive_parts.html:21 #: part/templates/part/part_base.html:129 templates/js/part.js:414 @@ -3000,7 +3221,7 @@ msgstr "" #: order/templates/order/receive_parts.html:23 msgid "Receive" -msgstr "" +msgstr "Odbierz" #: order/templates/order/receive_parts.html:36 msgid "Error: Referenced part has been removed" @@ -3008,7 +3229,7 @@ msgstr "" #: order/templates/order/receive_parts.html:57 msgid "Remove line" -msgstr "" +msgstr "Usuń linie" #: order/templates/order/sales_order_base.html:15 msgid "This SalesOrder has not been fully allocated" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" -msgstr "" +msgstr "Akcje" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" -msgstr "" +msgstr "Numer ID" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" -msgstr "" +msgstr "Przydzielono" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "Oblicz cenę" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,172 +3370,197 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" -msgstr "" +msgstr "Wyślij zamówienie" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" -msgstr "" +msgstr "Otrzymane przedmioty" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" -msgstr "" +msgstr "Nie ustawiono miejsca docelowego" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" -msgstr "" +msgstr "Błąd konwersji ilości na liczbę" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "Nie znaleziono ceny" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" -msgstr "" +msgstr "Domyślna lokalizacja" #: part/bom.py:139 part/templates/part/part_base.html:117 msgid "Available Stock" -msgstr "" +msgstr "Dostępna ilość" #: part/bom.py:379 #, python-brace-format @@ -3318,15 +3577,15 @@ msgstr "" #: part/forms.py:89 stock/forms.py:265 msgid "File Format" -msgstr "" +msgstr "Format pliku" #: part/forms.py:89 stock/forms.py:265 msgid "Select output file format" -msgstr "" +msgstr "Wybierz format pliku wyjściowego" #: part/forms.py:91 msgid "Cascading" -msgstr "" +msgstr "Kaskadowe" #: part/forms.py:91 msgid "Download cascading / multi-level BOM" @@ -3334,7 +3593,7 @@ msgstr "" #: part/forms.py:93 msgid "Levels" -msgstr "" +msgstr "Poziomy" #: part/forms.py:93 msgid "Select maximum number of BOM levels to export (0 = all levels)" @@ -3372,9 +3631,9 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" -msgstr "" +msgstr "Część nadrzędna" #: part/forms.py:123 part/templates/part/bom_duplicate.html:7 msgid "Select parent part to copy BOM from" @@ -3390,7 +3649,7 @@ msgstr "" #: part/forms.py:153 msgid "validate" -msgstr "" +msgstr "potwierdź" #: part/forms.py:153 msgid "Confirm that the BOM is correct" @@ -3448,9 +3707,9 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" -msgstr "" +msgstr "Podczęść" #: part/forms.py:372 msgid "Input quantity for price calculation" @@ -3462,20 +3721,20 @@ msgstr "" #: part/models.py:76 msgid "Default keywords" -msgstr "" +msgstr "Domyślne słowa kluczowe" #: part/models.py:76 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3523,25 +3782,25 @@ msgstr "" #: part/models.py:705 part/templates/part/detail.html:60 msgid "Variant Of" -msgstr "" +msgstr "Wariant" #: part/models.py:711 msgid "Part description" -msgstr "" +msgstr "Opis części" #: part/models.py:716 part/templates/part/category.html:73 #: part/templates/part/detail.html:67 msgid "Keywords" -msgstr "" +msgstr "Słowa kluczowe" #: part/models.py:717 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" -msgstr "" +msgstr "Kategoria" #: part/models.py:725 msgid "Part category" @@ -3550,7 +3809,7 @@ msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 #: part/templates/part/part_base.html:94 templates/js/part.js:161 msgid "IPN" -msgstr "" +msgstr "IPN" #: part/models.py:731 msgid "Internal Part Number" @@ -3563,7 +3822,7 @@ msgstr "" #: part/models.py:738 part/templates/part/detail.html:35 report/models.py:198 #: templates/js/part.js:165 msgid "Revision" -msgstr "" +msgstr "Wersja" #: part/models.py:760 msgid "Where is this item normally stored?" @@ -3587,16 +3846,16 @@ msgstr "" #: part/models.py:821 part/templates/part/detail.html:113 msgid "Minimum Stock" -msgstr "" +msgstr "Minimalny stan magazynowy" #: part/models.py:822 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" -msgstr "" +msgstr "Jednostki" #: part/models.py:829 msgid "Stock keeping units for this part" @@ -3623,14 +3882,14 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" -msgstr "" +msgstr "Aktywny" #: part/models.py:862 msgid "Is this part active?" -msgstr "" +msgstr "Czy ta część jest aktywna?" #: part/models.py:867 msgid "Is this a virtual part, such as a software product or license?" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 +#: part/models.py:1616 +msgid "Sell multiple" +msgstr "Sprzedaj wiele" + +#: part/models.py:1987 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1966 +#: part/models.py:2004 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" -msgstr "" +msgstr "Nazwa testu" -#: part/models.py:1987 +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" -msgstr "" +msgstr "Wymagane" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" -msgstr "" +msgstr "Dane" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" -msgstr "" +msgstr "Wartość domyślna" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" -msgstr "" +msgstr "Suma kontrolna" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" -msgstr "" +msgstr "Część 1" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" -msgstr "" +msgstr "Część 2" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" -msgstr "" +msgstr "Wybierz powiązaną część" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3843,7 +4106,7 @@ msgstr "" #: part/templates/part/bom.html:10 part/templates/part/navbar.html:48 #: part/templates/part/navbar.html:51 msgid "Bill of Materials" -msgstr "" +msgstr "Zestawienie materiałowe" #: part/templates/part/bom.html:19 #, python-format @@ -3866,11 +4129,11 @@ msgstr "" #: part/templates/part/bom.html:35 msgid "Import BOM data" -msgstr "" +msgstr "Importuj dane BOM" #: part/templates/part/bom.html:39 msgid "Copy BOM from parent part" -msgstr "" +msgstr "Kopiuj BOM z części nadrzędnej" #: part/templates/part/bom.html:43 msgid "New BOM Item" @@ -3878,7 +4141,7 @@ msgstr "" #: part/templates/part/bom.html:46 msgid "Finish Editing" -msgstr "" +msgstr "Zakończ edycję" #: part/templates/part/bom.html:51 msgid "Edit BOM" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4021,11 +4247,11 @@ msgstr "" #: part/templates/part/category.html:24 msgid "All parts" -msgstr "" +msgstr "Wszystkie części" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" -msgstr "" +msgstr "Stwórz nową kategorię komponentów" #: part/templates/part/category.html:35 msgid "Edit part category" @@ -4091,9 +4317,9 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" -msgstr "" +msgstr "Utwórz nową lokalizację magazynową" #: part/templates/part/category_delete.html:5 msgid "Are you sure you want to delete category" @@ -4110,7 +4336,7 @@ msgstr "" #: part/templates/part/category_delete.html:11 msgid "category" -msgstr "" +msgstr "kategoria" #: part/templates/part/category_delete.html:13 msgid "top level Parts category" @@ -4134,16 +4360,16 @@ msgstr "" #: part/templates/part/category_navbar.html:37 #: part/templates/part/navbar.html:22 msgid "Parameters" -msgstr "" +msgstr "Parametry" #: part/templates/part/category_parametric.html:10 #: part/templates/part/navbar.html:19 part/templates/part/params.html:10 msgid "Part Parameters" -msgstr "" +msgstr "Parametry części" #: part/templates/part/copy_part.html:9 part/views.py:460 msgid "Duplicate Part" -msgstr "" +msgstr "Duplikuj część" #: part/templates/part/copy_part.html:10 #, python-format @@ -4167,11 +4393,11 @@ msgstr "" #: part/templates/part/detail.html:11 part/templates/part/navbar.html:11 msgid "Part Details" -msgstr "" +msgstr "Szczegóły części" #: part/templates/part/detail.html:42 msgid "Latest Serial Number" -msgstr "" +msgstr "Ostatni numer seryjny" #: part/templates/part/detail.html:47 msgid "No serial numbers recorded" @@ -4183,15 +4409,15 @@ msgstr "" #: part/templates/part/detail.html:139 msgid "Responsible User" -msgstr "" +msgstr "Odpowiedzialny użytkownik" #: part/templates/part/detail.html:153 msgid "Part is virtual (not a physical part)" -msgstr "" +msgstr "Część jest wirtualna (nie fizyczna)" #: part/templates/part/detail.html:155 msgid "Part is not a virtual part" -msgstr "" +msgstr "Część nie jest częścią wirtualną" #: part/templates/part/detail.html:163 msgid "Part is a template part (variants can be made from this part)" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/ru/LC_MESSAGES/django.po b/InvenTree/locale/ru/LC_MESSAGES/django.po index d14c214d50..df6f0336c7 100644 --- a/InvenTree/locale/ru/LC_MESSAGES/django.po +++ b/InvenTree/locale/ru/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" "Last-Translator: \n" "Language-Team: Russian\n" "Language: ru_RU\n" @@ -11,6 +11,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: ru\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" @@ -72,8 +77,8 @@ msgstr "" msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -101,7 +106,7 @@ msgstr "" msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" msgstr "" @@ -117,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" msgstr "" @@ -127,8 +132,8 @@ msgstr "" msgid "upload date" msgstr "" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -136,11 +141,11 @@ msgid "Name" msgstr "" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,7 +159,7 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "" @@ -166,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -198,60 +203,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -376,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -416,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -446,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -517,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -667,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1112,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1168,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1202,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2393,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/tr/LC_MESSAGES/django.po b/InvenTree/locale/tr/LC_MESSAGES/django.po index db257af1fe..9d3d99e1c6 100644 --- a/InvenTree/locale/tr/LC_MESSAGES/django.po +++ b/InvenTree/locale/tr/LC_MESSAGES/django.po @@ -1,152 +1,151 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 10:47\n" +"Last-Translator: \n" +"Language-Team: Turkish\n" +"Language: tr_TR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: tr\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" -msgstr "" +msgstr "API uçnoktası bulunmadı" #: InvenTree/api.py:110 msgid "No action specified" -msgstr "" +msgstr "Hiçbir eylem belirtilmedi" #: InvenTree/api.py:124 msgid "No matching action found" -msgstr "" +msgstr "Eşleşen eylem bulunamadı" #: InvenTree/fields.py:44 msgid "Enter date" -msgstr "" +msgstr "Tarih giriniz" #: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" -msgstr "" +msgstr "Onay" #: InvenTree/forms.py:126 msgid "Confirm delete" -msgstr "" +msgstr "Silmeyi Onayla" #: InvenTree/forms.py:127 msgid "Confirm item deletion" -msgstr "" +msgstr "Silmeyi onayla" #: InvenTree/forms.py:159 templates/registration/login.html:77 msgid "Enter password" -msgstr "" +msgstr "Şifrenizi girin" #: InvenTree/forms.py:160 msgid "Enter new password" -msgstr "" +msgstr "Lütfen Yeni Parolayı Girin" #: InvenTree/forms.py:167 msgid "Confirm password" -msgstr "" +msgstr "Parolayı doğrulayın" #: InvenTree/forms.py:168 msgid "Confirm new password" -msgstr "" +msgstr "Yeni parolayı doğrulayın" #: InvenTree/forms.py:203 msgid "Apply Theme" -msgstr "" +msgstr "Temayı Uygula" #: InvenTree/forms.py:233 msgid "Select Category" -msgstr "" +msgstr "Kategori Seçin" #: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" -msgstr "" +msgstr "Tekrarlanan seri {n}" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" -msgstr "" +msgstr "Geçersiz veri sağlandı" #: InvenTree/helpers.py:387 msgid "Empty serial number string" -msgstr "" +msgstr "Boş seri numarası dizesi" #: InvenTree/helpers.py:409 InvenTree/helpers.py:412 InvenTree/helpers.py:415 #: InvenTree/helpers.py:440 #, python-brace-format msgid "Invalid group: {g}" -msgstr "" +msgstr "Geçersiz grup: {g}" #: InvenTree/helpers.py:445 #, python-brace-format msgid "Duplicate serial: {g}" -msgstr "" +msgstr "Tekrarlanan seri {g}" #: InvenTree/helpers.py:453 msgid "No serial numbers found" -msgstr "" +msgstr "Seri numarası bulunamadı" #: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" -msgstr "" +msgstr "Benzersiz serinin numaraları ({s}) miktarla eşleşmeli ({q})" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" -msgstr "" +msgstr "Ek" #: InvenTree/models.py:60 msgid "Select file to attach" -msgstr "" +msgstr "Eklenecek dosyayı seç" #: InvenTree/models.py:62 templates/attachment_table.html:16 msgid "Comment" -msgstr "" +msgstr "Yorum" #: InvenTree/models.py:62 msgid "File comment" -msgstr "" +msgstr "Yorum" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" -msgstr "" +msgstr "Kullanıcı" #: InvenTree/models.py:72 msgid "upload date" -msgstr "" +msgstr "Yükleme tarihi" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 msgid "Name" -msgstr "" +msgstr "Adı" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -160,123 +159,200 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" -msgstr "" +msgstr "Açıklama" #: InvenTree/models.py:115 msgid "Description (optional)" -msgstr "" +msgstr "Açıklama(opsiyonel)" #: InvenTree/models.py:123 msgid "parent" -msgstr "" +msgstr "ebeveyn" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" -msgstr "" +msgstr "İngilizce" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" -msgstr "" +msgstr "Fransızca" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" -msgstr "" +msgstr "Almanca" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" -msgstr "" +msgstr "Polonyaca" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" -msgstr "" +msgstr "Türkçe" #: InvenTree/status.py:93 msgid "Background worker check failed" -msgstr "" +msgstr "Arka plan çalışanı kontrolü başarısız oldu" #: InvenTree/status.py:97 msgid "Email backend not configured" -msgstr "" +msgstr "E-posta arka ucu yapılandırılmadı" #: InvenTree/status.py:100 msgid "InvenTree system health checks failed" -msgstr "" +msgstr "InvenTree sistem sağlık kontrolü başarısız" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" -msgstr "" +msgstr "Bekliyor" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" -msgstr "" +msgstr "Sipariş verildi" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" -msgstr "" - -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 -msgid "Cancelled" -msgstr "" - -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 -msgid "Lost" -msgstr "" +msgstr "Tamamlandı" #: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 -msgid "Returned" -msgstr "" +#: InvenTree/status_codes.py:316 +msgid "Cancelled" +msgstr "İptal edildi" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 +msgid "Lost" +msgstr "Kayıp" + +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 +msgid "Returned" +msgstr "İade" + +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" -msgstr "" - -#: InvenTree/status_codes.py:184 -msgid "OK" -msgstr "" - -#: InvenTree/status_codes.py:185 -msgid "Attention needed" -msgstr "" +msgstr "Sevk edildi" #: InvenTree/status_codes.py:186 -msgid "Damaged" -msgstr "" +msgid "OK" +msgstr "TAMAM" #: InvenTree/status_codes.py:187 -msgid "Destroyed" -msgstr "" +msgid "Attention needed" +msgstr "Dikkat gerekli" + +#: InvenTree/status_codes.py:188 +msgid "Damaged" +msgstr "Hasarlı" #: InvenTree/status_codes.py:189 +msgid "Destroyed" +msgstr "Kullanılamaz durumda" + +#: InvenTree/status_codes.py:191 msgid "Rejected" +msgstr "Reddedildi" + +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" msgstr "" -#: InvenTree/status_codes.py:237 -msgid "Production" +#: InvenTree/status_codes.py:274 +msgid "Stock item created" msgstr "" +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 +msgid "Production" +msgstr "Üretim" + #: InvenTree/validators.py:22 msgid "Not a valid currency code" -msgstr "" +msgstr "Geçerli para birimi yok" #: InvenTree/validators.py:50 msgid "Invalid character in part name" -msgstr "" +msgstr "Parça adında geçersiniz karakter bulunuyor" #: InvenTree/validators.py:63 #, python-brace-format msgid "IPN must match regex pattern {pat}" -msgstr "" +msgstr "IPN regex kalıbıyla eşleşmelidir {pat}" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -382,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -422,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -452,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -465,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -523,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -547,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -566,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -622,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -635,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -673,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -716,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -818,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -838,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -903,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -914,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -961,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1118,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1174,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1208,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1237,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1354,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1727,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1764,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1999,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2028,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2045,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2094,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2141,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2211,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2264,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2319,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2369,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2399,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2419,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2439,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2471,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2479,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2495,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2577,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2613,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2654,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2663,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2836,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2870,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2942,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2952,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2986,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3048,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3142,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3378,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3454,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3474,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3544,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3599,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3629,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3666,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3911,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3929,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -4004,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4029,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4097,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4288,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4321,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4357,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4398,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4426,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4570,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4719,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4877,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4899,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4942,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4999,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5290,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5528,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5568,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5601,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5768,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5902,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6106,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6116,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6172,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6317,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6415,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6548,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6746,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6770,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7009,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7121,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7264,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/InvenTree/locale/zh/LC_MESSAGES/django.po b/InvenTree/locale/zh/LC_MESSAGES/django.po index 2075ec9326..c897b54b5a 100644 --- a/InvenTree/locale/zh/LC_MESSAGES/django.po +++ b/InvenTree/locale/zh/LC_MESSAGES/django.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" +"Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-05 17:33+1000\n" -"PO-Revision-Date: 2021-04-21 09:33\n" +"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"PO-Revision-Date: 2021-05-17 14:58\n" "Last-Translator: \n" "Language-Team: Chinese Simplified\n" "Language: zh_CN\n" @@ -11,33 +11,38 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +"X-Crowdin-Project: inventree\n" +"X-Crowdin-Project-ID: 452300\n" +"X-Crowdin-Language: zh-CN\n" +"X-Crowdin-File: /[inventree.InvenTree] l10/InvenTree/locale/en/LC_MESSAGES/django.po\n" +"X-Crowdin-File-ID: 138\n" #: InvenTree/api.py:64 msgid "API endpoint not found" -msgstr "" +msgstr "未找到 API 端点" #: InvenTree/api.py:110 msgid "No action specified" -msgstr "" +msgstr "未指定操作" #: InvenTree/api.py:124 msgid "No matching action found" -msgstr "" +msgstr "未找到指定操作" #: InvenTree/fields.py:44 msgid "Enter date" -msgstr "" +msgstr "输入日期" #: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" -msgstr "" +msgstr "确认" #: InvenTree/forms.py:126 msgid "Confirm delete" -msgstr "" +msgstr "确认删除" #: InvenTree/forms.py:127 msgid "Confirm item deletion" @@ -45,35 +50,35 @@ msgstr "" #: InvenTree/forms.py:159 templates/registration/login.html:77 msgid "Enter password" -msgstr "" +msgstr "输入密码" #: InvenTree/forms.py:160 msgid "Enter new password" -msgstr "" +msgstr "输入新密码" #: InvenTree/forms.py:167 msgid "Confirm password" -msgstr "" +msgstr "确认密码" #: InvenTree/forms.py:168 msgid "Confirm new password" -msgstr "" +msgstr "确认新密码" #: InvenTree/forms.py:203 msgid "Apply Theme" -msgstr "" +msgstr "应用主题" #: InvenTree/forms.py:233 msgid "Select Category" -msgstr "" +msgstr "选择分类" #: InvenTree/helpers.py:377 #, python-brace-format msgid "Duplicate serial: {n}" msgstr "" -#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:353 -#: stock/views.py:1763 +#: InvenTree/helpers.py:384 order/models.py:245 order/models.py:355 +#: stock/views.py:1795 msgid "Invalid quantity provided" msgstr "" @@ -94,53 +99,53 @@ msgstr "" #: InvenTree/helpers.py:453 msgid "No serial numbers found" -msgstr "" +msgstr "未找到序列号" #: InvenTree/helpers.py:457 #, python-brace-format msgid "Number of unique serial number ({s}) must match quantity ({q})" msgstr "" -#: InvenTree/models.py:59 stock/models.py:1662 +#: InvenTree/models.py:59 stock/models.py:1761 msgid "Attachment" -msgstr "" +msgstr "附件" #: InvenTree/models.py:60 msgid "Select file to attach" -msgstr "" +msgstr "选择附件" #: InvenTree/models.py:62 templates/attachment_table.html:16 msgid "Comment" -msgstr "" +msgstr "注释" #: InvenTree/models.py:62 msgid "File comment" -msgstr "" +msgstr "文件注释" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1908 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1041 +#: templates/js/stock.js:1146 msgid "User" -msgstr "" +msgstr "用户" #: InvenTree/models.py:72 msgid "upload date" -msgstr "" +msgstr "上传日期" -#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:101 -#: part/models.py:686 part/models.py:2049 part/templates/part/params.html:27 +#: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 +#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 msgid "Name" -msgstr "" +msgstr "名称" #: InvenTree/models.py:114 build/models.py:134 -#: build/templates/build/detail.html:21 company/models.py:342 -#: company/models.py:494 company/templates/company/detail.html:27 +#: build/templates/build/detail.html:21 company/models.py:339 +#: company/models.py:491 company/templates/company/detail.html:27 #: company/templates/company/manufacturer_part_base.html:72 #: company/templates/company/supplier_part_base.html:71 -#: company/templates/company/supplier_part_detail.html:31 label/models.py:108 +#: company/templates/company/supplier_part_detail.html:31 label/models.py:109 #: order/models.py:101 order/templates/order/purchase_order_detail.html:143 #: part/models.py:710 part/templates/part/detail.html:54 #: part/templates/part/set_category.html:14 report/models.py:192 @@ -154,7 +159,7 @@ msgstr "" #: templates/js/order.js:280 templates/js/part.js:169 templates/js/part.js:252 #: templates/js/part.js:371 templates/js/part.js:565 templates/js/part.js:643 #: templates/js/stock.js:554 templates/js/stock.js:956 -#: templates/js/stock.js:1015 +#: templates/js/stock.js:1001 msgid "Description" msgstr "" @@ -166,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:491 +#: InvenTree/settings.py:501 msgid "English" msgstr "" -#: InvenTree/settings.py:492 +#: InvenTree/settings.py:502 msgid "French" msgstr "" -#: InvenTree/settings.py:493 +#: InvenTree/settings.py:503 msgid "German" msgstr "" -#: InvenTree/settings.py:494 +#: InvenTree/settings.py:504 msgid "Polish" msgstr "" -#: InvenTree/settings.py:495 +#: InvenTree/settings.py:505 msgid "Turkish" msgstr "" @@ -198,60 +203,136 @@ msgstr "" msgid "InvenTree system health checks failed" msgstr "" -#: InvenTree/status_codes.py:102 InvenTree/status_codes.py:143 -#: InvenTree/status_codes.py:236 +#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:145 +#: InvenTree/status_codes.py:314 msgid "Pending" msgstr "" -#: InvenTree/status_codes.py:103 +#: InvenTree/status_codes.py:105 msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:104 InvenTree/status_codes.py:239 +#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:317 msgid "Complete" msgstr "" -#: InvenTree/status_codes.py:105 InvenTree/status_codes.py:145 -#: InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 +#: InvenTree/status_codes.py:316 msgid "Cancelled" msgstr "" -#: InvenTree/status_codes.py:106 InvenTree/status_codes.py:146 -#: InvenTree/status_codes.py:188 +#: InvenTree/status_codes.py:108 InvenTree/status_codes.py:148 +#: InvenTree/status_codes.py:190 msgid "Lost" msgstr "" -#: InvenTree/status_codes.py:107 InvenTree/status_codes.py:147 -#: InvenTree/status_codes.py:190 +#: InvenTree/status_codes.py:109 InvenTree/status_codes.py:149 +#: InvenTree/status_codes.py:192 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:144 +#: InvenTree/status_codes.py:146 #: order/templates/order/sales_order_base.html:124 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:184 +#: InvenTree/status_codes.py:186 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:185 +#: InvenTree/status_codes.py:187 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:186 +#: InvenTree/status_codes.py:188 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:187 +#: InvenTree/status_codes.py:189 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:189 +#: InvenTree/status_codes.py:191 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:272 +msgid "Legacy stock tracking entry" +msgstr "" + +#: InvenTree/status_codes.py:274 +msgid "Stock item created" +msgstr "" + +#: InvenTree/status_codes.py:276 +msgid "Edited stock item" +msgstr "" + +#: InvenTree/status_codes.py:277 +msgid "Assigned serial number" +msgstr "" + +#: InvenTree/status_codes.py:279 +msgid "Stock counted" +msgstr "" + +#: InvenTree/status_codes.py:280 +msgid "Stock manually added" +msgstr "" + +#: InvenTree/status_codes.py:281 +msgid "Stock manually removed" +msgstr "" + +#: InvenTree/status_codes.py:283 +msgid "Location changed" +msgstr "" + +#: InvenTree/status_codes.py:285 +msgid "Installed into assembly" +msgstr "" + +#: InvenTree/status_codes.py:286 +msgid "Removed from assembly" +msgstr "" + +#: InvenTree/status_codes.py:288 +msgid "Installed component item" +msgstr "" + +#: InvenTree/status_codes.py:289 +msgid "Removed component item" +msgstr "" + +#: InvenTree/status_codes.py:291 +msgid "Split from parent item" +msgstr "" + +#: InvenTree/status_codes.py:292 +msgid "Split child item" +msgstr "" + +#: InvenTree/status_codes.py:294 templates/js/table_filters.js:177 +msgid "Sent to customer" +msgstr "" + +#: InvenTree/status_codes.py:295 +msgid "Returned from customer" +msgstr "" + +#: InvenTree/status_codes.py:297 +msgid "Build order output created" +msgstr "" + +#: InvenTree/status_codes.py:298 +msgid "Build order output completed" +msgstr "" + +#: InvenTree/status_codes.py:300 +msgid "Received against purchase order" +msgstr "" + +#: InvenTree/status_codes.py:315 msgid "Production" msgstr "" @@ -270,7 +351,8 @@ msgstr "" #: InvenTree/validators.py:77 InvenTree/validators.py:91 #: InvenTree/validators.py:105 -msgid "Reference must match pattern" +#, python-brace-format +msgid "Reference must match pattern {pattern}" msgstr "" #: InvenTree/validators.py:113 @@ -376,35 +458,35 @@ msgstr "" msgid "Target date for build completion. Build will be overdue after this date." msgstr "" -#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1241 +#: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 #: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:703 +#: build/templates/build/detail.html:31 common/models.py:705 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 -#: order/forms.py:188 order/forms.py:205 order/forms.py:239 order/forms.py:261 -#: order/forms.py:278 order/models.py:603 order/models.py:794 +#: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 +#: order/forms.py:279 order/models.py:614 order/models.py:815 +#: order/templates/order/order_wizard/match_parts.html:29 #: order/templates/order/order_wizard/select_parts.html:32 #: order/templates/order/purchase_order_detail.html:175 #: order/templates/order/sales_order_detail.html:70 #: order/templates/order/sales_order_detail.html:77 -#: order/templates/order/sales_order_detail.html:159 -#: order/templates/order/sales_order_detail.html:224 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2178 +#: order/templates/order/sales_order_detail.html:162 +#: order/templates/order/sales_order_detail.html:230 part/forms.py:342 +#: part/forms.py:371 part/forms.py:387 part/models.py:2216 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:11 -#: part/templates/part/part_pricing.html:18 +#: part/templates/part/part_pricing.html:13 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 -#: stock/forms.py:175 stock/forms.py:308 stock/models.py:1566 -#: stock/templates/stock/item_base.html:244 +#: stock/forms.py:175 stock/forms.py:308 +#: stock/templates/stock/item_base.html:250 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1033 templates/js/stock.js:1271 +#: templates/js/stock.js:1131 templates/js/stock.js:1393 msgid "Quantity" msgstr "" @@ -416,7 +498,7 @@ msgstr "" msgid "Enter quantity for build output" msgstr "" -#: build/forms.py:95 order/forms.py:233 stock/forms.py:118 +#: build/forms.py:95 order/forms.py:234 stock/forms.py:118 msgid "Serial Numbers" msgstr "" @@ -446,11 +528,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:274 +#: stock/templates/stock/item_base.html:280 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 +#: templates/js/stock.js:641 templates/js/stock.js:1023 msgid "Location" msgstr "" @@ -459,12 +541,13 @@ msgid "Location of completed parts" msgstr "" #: build/forms.py:215 build/templates/build/build_base.html:128 -#: build/templates/build/detail.html:59 order/models.py:455 +#: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:392 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1279 +#: templates/js/stock.js:628 templates/js/stock.js:1100 +#: templates/js/stock.js:1401 msgid "Status" msgstr "" @@ -517,9 +600,9 @@ msgstr "" msgid "Build Order Reference" msgstr "" -#: build/models.py:127 order/models.py:99 order/models.py:605 +#: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:219 part/models.py:2187 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -541,16 +624,16 @@ msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:118 -#: build/templates/build/detail.html:26 company/models.py:688 -#: order/models.py:647 order/models.py:679 +#: build/templates/build/detail.html:26 company/models.py:622 +#: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 -#: order/templates/order/sales_order_detail.html:207 part/models.py:321 -#: part/models.py:1876 part/models.py:1888 part/models.py:1906 -#: part/models.py:1981 part/models.py:2077 part/models.py:2162 +#: order/templates/order/sales_order_detail.html:213 part/models.py:321 +#: part/models.py:1914 part/models.py:1926 part/models.py:1944 +#: part/models.py:2019 part/models.py:2115 part/models.py:2200 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:14 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -560,7 +643,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1343 +#: templates/js/stock.js:1465 msgid "Part" msgstr "" @@ -616,7 +699,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:212 stock/models.py:432 +#: build/models.py:212 stock/models.py:464 msgid "Batch Code" msgstr "" @@ -629,7 +712,7 @@ msgstr "" msgid "Creation Date" msgstr "" -#: build/models.py:223 order/models.py:461 +#: build/models.py:223 order/models.py:472 msgid "Target completion date" msgstr "" @@ -667,28 +750,28 @@ msgstr "" #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 #: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:426 stock/templates/stock/item_base.html:334 +#: stock/models.py:458 stock/templates/stock/item_base.html:340 msgid "External Link" msgstr "" -#: build/models.py:257 part/models.py:744 stock/models.py:428 +#: build/models.py:257 part/models.py:744 stock/models.py:460 msgid "Link to external URL" msgstr "" #: build/models.py:261 build/templates/build/navbar.html:53 -#: company/models.py:135 company/models.py:501 +#: company/models.py:132 company/models.py:498 #: company/templates/company/navbar.html:70 #: company/templates/company/navbar.html:73 order/models.py:123 -#: order/models.py:607 order/templates/order/po_navbar.html:29 +#: order/models.py:618 order/templates/order/po_navbar.html:29 #: order/templates/order/po_navbar.html:32 #: order/templates/order/purchase_order_detail.html:209 -#: order/templates/order/sales_order_detail.html:264 +#: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 #: part/templates/part/navbar.html:128 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 -#: stock/models.py:498 stock/models.py:1558 stock/models.py:1668 +#: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 #: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" @@ -710,75 +793,71 @@ msgstr "" msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:838 -msgid "Completed build output" -msgstr "" - -#: build/models.py:1132 +#: build/models.py:1136 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:1157 -msgid "Build item must specify a build output, as master part is marked as trackable" -msgstr "" - #: build/models.py:1161 -#, python-brace-format -msgid "Selected stock item not found in BOM for part '{p}'" +msgid "Build item must specify a build output, as master part is marked as trackable" msgstr "" #: build/models.py:1165 #, python-brace-format +msgid "Selected stock item not found in BOM for part '{p}'" +msgstr "" + +#: build/models.py:1169 +#, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:1172 order/models.py:768 +#: build/models.py:1176 order/models.py:789 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:1176 order/models.py:771 +#: build/models.py:1180 order/models.py:792 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:1180 +#: build/models.py:1184 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1220 stock/templates/stock/item_base.html:306 +#: build/models.py:1224 stock/templates/stock/item_base.html:312 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" msgstr "" -#: build/models.py:1221 +#: build/models.py:1225 msgid "Build to allocate parts" msgstr "" -#: build/models.py:1228 part/templates/part/allocation.html:18 +#: build/models.py:1232 part/templates/part/allocation.html:18 #: part/templates/part/allocation.html:24 #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:328 +#: stock/templates/stock/item_base.html:334 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1004 templates/js/stock.js:1262 +#: templates/js/stock.js:1082 templates/js/stock.js:1384 msgid "Stock Item" msgstr "" -#: build/models.py:1229 +#: build/models.py:1233 msgid "Source stock item" msgstr "" -#: build/models.py:1242 +#: build/models.py:1246 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:1250 +#: build/models.py:1254 msgid "Install into" msgstr "" -#: build/models.py:1251 +#: build/models.py:1255 msgid "Destination stock item" msgstr "" @@ -812,7 +891,7 @@ msgstr "" #: build/templates/build/allocate.html:30 #: company/templates/company/detail_manufacturer_part.html:33 -#: company/templates/company/detail_supplier_part.html:32 order/views.py:795 +#: company/templates/company/detail_supplier_part.html:32 order/views.py:986 #: part/templates/part/category.html:127 msgid "Order Parts" msgstr "" @@ -832,9 +911,9 @@ msgstr "" #: build/templates/build/allocation_card.html:21 #: build/templates/build/complete_output.html:46 #: order/templates/order/sales_order_detail.html:75 -#: order/templates/order/sales_order_detail.html:157 +#: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:420 stock/templates/stock/item_base.html:238 +#: stock/models.py:452 stock/templates/stock/item_base.html:244 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -897,7 +976,7 @@ msgstr "" #: order/templates/order/order_base.html:26 #: order/templates/order/sales_order_base.html:35 #: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:118 +#: stock/templates/stock/item_base.html:124 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" @@ -908,8 +987,8 @@ msgstr "" #: order/templates/order/order_base.html:86 #: order/templates/order/sales_order_base.html:41 #: order/templates/order/sales_order_base.html:86 -#: templates/js/table_filters.js:240 templates/js/table_filters.js:259 -#: templates/js/table_filters.js:276 +#: templates/js/table_filters.js:241 templates/js/table_filters.js:260 +#: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" @@ -955,14 +1034,14 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:160 -#: build/templates/build/detail.html:84 order/models.py:677 +#: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:268 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 msgid "Sales Order" msgstr "" @@ -1112,9 +1191,9 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:292 templates/js/stock.js:636 -#: templates/js/stock.js:1286 templates/js/table_filters.js:107 -#: templates/js/table_filters.js:201 +#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 +#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: templates/js/table_filters.js:202 msgid "Batch" msgstr "" @@ -1168,6 +1247,7 @@ msgstr "" #: company/templates/company/navbar.html:15 #: order/templates/order/po_navbar.html:14 #: order/templates/order/so_navbar.html:15 part/templates/part/navbar.html:15 +#: templates/js/stock.js:1016 msgid "Details" msgstr "" @@ -1202,7 +1282,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:470 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 +#: stock/templates/stock/item_base.html:487 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1231,7 +1312,7 @@ msgstr "" msgid "Maximum output quantity is " msgstr "" -#: build/views.py:184 stock/models.py:969 stock/views.py:1789 +#: build/views.py:184 stock/views.py:1821 msgid "Serial numbers already exist" msgstr "" @@ -1348,372 +1429,405 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:110 order/views.py:162 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 #: stock/views.py:277 msgid "Added attachment" msgstr "" -#: build/views.py:1119 order/views.py:189 order/views.py:210 +#: build/views.py:1119 order/views.py:194 order/views.py:215 msgid "Edit Attachment" msgstr "" -#: build/views.py:1129 order/views.py:193 order/views.py:214 +#: build/views.py:1129 order/views.py:198 order/views.py:219 msgid "Attachment updated" msgstr "" -#: build/views.py:1139 order/views.py:229 order/views.py:243 +#: build/views.py:1139 order/views.py:234 order/views.py:248 msgid "Delete Attachment" msgstr "" -#: build/views.py:1144 order/views.py:235 order/views.py:249 stock/views.py:333 +#: build/views.py:1144 order/views.py:240 order/views.py:254 stock/views.py:333 msgid "Deleted attachment" msgstr "" -#: common/models.py:56 -msgid "InvenTree Instance Name" +#: common/files.py:64 +msgid "Unsupported file format: {ext.upper()}" +msgstr "" + +#: common/files.py:69 +msgid "Error reading file (invalid format)" +msgstr "" + +#: common/files.py:71 +msgid "Error reading file (incorrect dimension)" +msgstr "" + +#: common/files.py:73 +msgid "Error reading file (data could be corrupted)" +msgstr "" + +#: common/forms.py:38 templates/attachment_table.html:15 +msgid "File" +msgstr "" + +#: common/forms.py:39 +msgid "Select file to upload" +msgstr "" + +#: common/forms.py:54 +msgid "{name.title()} File" +msgstr "" + +#: common/forms.py:55 +#, python-brace-format +msgid "Select {name} file to upload" msgstr "" #: common/models.py:58 +msgid "InvenTree Instance Name" +msgstr "" + +#: common/models.py:60 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:62 +#: common/models.py:64 msgid "Use instance name" msgstr "" -#: common/models.py:63 +#: common/models.py:65 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:69 company/models.py:97 company/models.py:98 +#: common/models.py:71 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:70 +#: common/models.py:72 msgid "Internal company name" msgstr "" -#: common/models.py:75 +#: common/models.py:77 msgid "Base URL" msgstr "" -#: common/models.py:76 +#: common/models.py:78 msgid "Base URL for server instance" msgstr "" -#: common/models.py:82 +#: common/models.py:84 msgid "Default Currency" msgstr "" -#: common/models.py:83 +#: common/models.py:85 msgid "Default currency" msgstr "" -#: common/models.py:89 +#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:90 +#: common/models.py:92 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:96 +#: common/models.py:98 msgid "Barcode Support" msgstr "" -#: common/models.py:97 +#: common/models.py:99 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:103 +#: common/models.py:105 msgid "IPN Regex" msgstr "" -#: common/models.py:104 +#: common/models.py:106 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:108 +#: common/models.py:110 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:109 +#: common/models.py:111 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:115 +#: common/models.py:117 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:116 +#: common/models.py:118 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:122 +#: common/models.py:124 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:123 +#: common/models.py:125 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:129 +#: common/models.py:131 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:130 +#: common/models.py:132 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:136 +#: common/models.py:138 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:137 +#: common/models.py:139 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:143 +#: common/models.py:145 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:144 +#: common/models.py:146 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:150 +#: common/models.py:152 msgid "Recent Part Count" msgstr "" -#: common/models.py:151 +#: common/models.py:153 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:157 part/models.py:2079 part/templates/part/detail.html:160 -#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:24 -#: templates/js/table_filters.js:310 +#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 +#: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:158 +#: common/models.py:160 msgid "Parts are templates by default" msgstr "" -#: common/models.py:164 part/models.py:834 part/templates/part/detail.html:170 -#: templates/js/table_filters.js:123 templates/js/table_filters.js:322 +#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:165 +#: common/models.py:167 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:171 part/models.py:840 part/templates/part/detail.html:180 -#: templates/js/table_filters.js:326 +#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:172 +#: common/models.py:174 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:178 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:179 +#: common/models.py:181 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:185 part/models.py:856 part/templates/part/detail.html:210 -#: templates/js/table_filters.js:334 +#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:186 +#: common/models.py:188 msgid "Parts are salable by default" msgstr "" -#: common/models.py:192 part/models.py:846 part/templates/part/detail.html:190 -#: templates/js/table_filters.js:32 templates/js/table_filters.js:338 +#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:193 +#: common/models.py:195 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:199 part/models.py:866 part/templates/part/detail.html:150 -#: templates/js/table_filters.js:28 +#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:200 +#: common/models.py:202 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:206 +#: common/models.py:208 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:207 +#: common/models.py:209 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:213 +#: common/models.py:215 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:214 +#: common/models.py:216 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:220 +#: common/models.py:222 msgid "Page Size" msgstr "" -#: common/models.py:221 +#: common/models.py:223 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:231 +#: common/models.py:233 msgid "Test Reports" msgstr "" -#: common/models.py:232 +#: common/models.py:234 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:238 +#: common/models.py:240 msgid "Stock Expiry" msgstr "" -#: common/models.py:239 +#: common/models.py:241 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:245 +#: common/models.py:247 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:246 +#: common/models.py:248 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:252 +#: common/models.py:254 msgid "Stock Stale Time" msgstr "" -#: common/models.py:253 +#: common/models.py:255 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:255 part/templates/part/detail.html:121 +#: common/models.py:257 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:260 +#: common/models.py:262 msgid "Build Expired Stock" msgstr "" -#: common/models.py:261 +#: common/models.py:263 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:267 +#: common/models.py:269 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:268 +#: common/models.py:270 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:274 +#: common/models.py:276 msgid "Group by Part" msgstr "" -#: common/models.py:275 +#: common/models.py:277 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:281 +#: common/models.py:283 msgid "Recent Stock Count" msgstr "" -#: common/models.py:282 +#: common/models.py:284 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:288 +#: common/models.py:290 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:289 +#: common/models.py:291 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:294 +#: common/models.py:296 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:295 +#: common/models.py:297 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:299 +#: common/models.py:301 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:300 +#: common/models.py:302 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:305 +#: common/models.py:307 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:306 +#: common/models.py:308 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:529 +#: common/models.py:531 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:531 +#: common/models.py:533 msgid "Settings value" msgstr "" -#: common/models.py:566 +#: common/models.py:568 msgid "Must be an integer value" msgstr "" -#: common/models.py:589 +#: common/models.py:591 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:600 +#: common/models.py:602 msgid "Value must be an integer value" msgstr "" -#: common/models.py:623 +#: common/models.py:625 msgid "Key string must be unique" msgstr "" -#: common/models.py:704 company/forms.py:177 +#: common/models.py:706 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:712 company/templates/company/supplier_part_pricing.html:82 +#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 #: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 msgid "Price" msgstr "" -#: common/models.py:713 +#: common/models.py:715 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:736 +#: common/models.py:804 msgid "Default" msgstr "" @@ -1721,24 +1835,42 @@ msgstr "" msgid "Current value" msgstr "" -#: common/views.py:25 +#: common/views.py:32 msgid "Change Setting" msgstr "" -#: common/views.py:94 +#: common/views.py:101 msgid "Supplied value is not allowed" msgstr "" -#: common/views.py:103 +#: common/views.py:110 msgid "Supplied value must be a boolean" msgstr "" -#: company/forms.py:38 company/models.py:145 +#: common/views.py:184 order/templates/order/order_wizard/po_upload.html:42 +#: order/views.py:582 part/templates/part/bom_upload/upload_file.html:27 +msgid "Upload File" +msgstr "" + +#: common/views.py:185 order/templates/order/order_wizard/match_fields.html:52 +#: order/views.py:583 part/templates/part/bom_upload/select_fields.html:58 +msgid "Match Fields" +msgstr "" + +#: common/views.py:186 +msgid "Match Items" +msgstr "" + +#: common/views.py:479 +msgid "Fields matching failed" +msgstr "" + +#: company/forms.py:38 company/models.py:142 #: company/templates/company/detail.html:42 msgid "Currency" msgstr "" -#: company/forms.py:39 company/models.py:147 +#: company/forms.py:39 company/models.py:144 msgid "Default currency used for this company" msgstr "" @@ -1758,216 +1890,216 @@ msgstr "" msgid "Single quantity price" msgstr "" -#: company/forms.py:128 company/models.py:324 +#: company/forms.py:128 company/models.py:321 msgid "Select manufacturer" msgstr "" -#: company/forms.py:134 company/models.py:331 +#: company/forms.py:134 company/models.py:328 msgid "Manufacturer Part Number" msgstr "" -#: company/forms.py:136 company/models.py:330 +#: company/forms.py:136 company/models.py:327 #: company/templates/company/manufacturer_part_base.html:89 #: company/templates/company/manufacturer_part_detail.html:26 -#: company/templates/company/supplier_part_base.html:101 +#: company/templates/company/supplier_part_base.html:102 #: company/templates/company/supplier_part_detail.html:35 #: order/templates/order/purchase_order_detail.html:158 part/bom.py:171 #: part/bom.py:242 templates/js/company.js:181 templates/js/company.js:307 msgid "MPN" msgstr "" -#: company/models.py:102 +#: company/models.py:99 msgid "Company description" msgstr "" -#: company/models.py:103 +#: company/models.py:100 msgid "Description of the company" msgstr "" -#: company/models.py:107 company/templates/company/company_base.html:70 +#: company/models.py:104 company/templates/company/company_base.html:70 #: company/templates/company/detail.html:33 templates/js/company.js:60 msgid "Website" msgstr "" -#: company/models.py:107 +#: company/models.py:104 msgid "Company website URL" msgstr "" -#: company/models.py:110 company/templates/company/company_base.html:77 +#: company/models.py:107 company/templates/company/company_base.html:77 msgid "Address" msgstr "" -#: company/models.py:111 +#: company/models.py:108 msgid "Company address" msgstr "" -#: company/models.py:114 +#: company/models.py:111 msgid "Phone number" msgstr "" -#: company/models.py:115 +#: company/models.py:112 msgid "Contact phone number" msgstr "" -#: company/models.py:118 company/templates/company/company_base.html:91 +#: company/models.py:115 company/templates/company/company_base.html:91 msgid "Email" msgstr "" -#: company/models.py:118 +#: company/models.py:115 msgid "Contact email address" msgstr "" -#: company/models.py:121 company/templates/company/company_base.html:98 +#: company/models.py:118 company/templates/company/company_base.html:98 msgid "Contact" msgstr "" -#: company/models.py:122 +#: company/models.py:119 msgid "Point of contact" msgstr "" -#: company/models.py:124 company/models.py:336 company/models.py:488 +#: company/models.py:121 company/models.py:333 company/models.py:485 #: order/models.py:103 part/models.py:743 #: report/templates/report/inventree_build_order_base.html:165 -#: stock/models.py:1560 templates/js/company.js:188 templates/js/company.js:318 +#: templates/js/company.js:188 templates/js/company.js:318 #: templates/js/part.js:431 msgid "Link" msgstr "" -#: company/models.py:124 +#: company/models.py:121 msgid "Link to external company information" msgstr "" -#: company/models.py:132 part/models.py:753 +#: company/models.py:129 part/models.py:753 msgid "Image" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "is customer" msgstr "" -#: company/models.py:137 +#: company/models.py:134 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "is supplier" msgstr "" -#: company/models.py:139 +#: company/models.py:136 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "is manufacturer" msgstr "" -#: company/models.py:141 +#: company/models.py:138 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:308 company/models.py:459 stock/models.py:373 -#: stock/templates/stock/item_base.html:224 +#: company/models.py:305 company/models.py:456 stock/models.py:405 +#: stock/templates/stock/item_base.html:230 msgid "Base Part" msgstr "" -#: company/models.py:312 company/models.py:463 order/views.py:1384 +#: company/models.py:309 company/models.py:460 order/views.py:1587 msgid "Select part" msgstr "" -#: company/models.py:323 company/templates/company/detail.html:57 +#: company/models.py:320 company/templates/company/detail.html:57 #: company/templates/company/manufacturer_part_base.html:85 #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:341 +#: part/bom.py:241 stock/templates/stock/item_base.html:347 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" msgstr "" -#: company/models.py:337 +#: company/models.py:334 msgid "URL for external manufacturer part link" msgstr "" -#: company/models.py:343 +#: company/models.py:340 msgid "Manufacturer part description" msgstr "" -#: company/models.py:469 company/templates/company/detail.html:62 +#: company/models.py:466 company/templates/company/detail.html:62 #: company/templates/company/supplier_part_base.html:84 #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:353 +#: part/bom.py:286 stock/templates/stock/item_base.html:359 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" msgstr "" -#: company/models.py:470 +#: company/models.py:467 msgid "Select supplier" msgstr "" -#: company/models.py:475 company/templates/company/supplier_part_base.html:88 +#: company/models.py:472 company/templates/company/supplier_part_base.html:88 #: company/templates/company/supplier_part_detail.html:26 #: order/templates/order/purchase_order_detail.html:149 part/bom.py:176 #: part/bom.py:287 msgid "SKU" msgstr "" -#: company/models.py:476 +#: company/models.py:473 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:482 +#: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:346 +#: stock/templates/stock/item_base.html:352 msgid "Manufacturer Part" msgstr "" -#: company/models.py:483 +#: company/models.py:480 msgid "Select manufacturer part" msgstr "" -#: company/models.py:489 +#: company/models.py:486 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:495 +#: company/models.py:492 msgid "Supplier part description" msgstr "" -#: company/models.py:500 company/templates/company/supplier_part_base.html:115 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2190 +#: company/models.py:497 company/templates/company/supplier_part_base.html:116 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "base cost" msgstr "" -#: company/models.py:504 +#: company/models.py:501 part/models.py:1614 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:506 company/templates/company/supplier_part_base.html:108 -#: stock/models.py:397 stock/templates/stock/item_base.html:299 +#: company/models.py:503 company/templates/company/supplier_part_base.html:109 +#: stock/models.py:429 stock/templates/stock/item_base.html:305 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" -#: company/models.py:506 +#: company/models.py:503 msgid "Part packaging" msgstr "" -#: company/models.py:508 +#: company/models.py:505 part/models.py:1616 msgid "multiple" msgstr "" -#: company/models.py:508 +#: company/models.py:505 msgid "Order multiple" msgstr "" @@ -1993,7 +2125,7 @@ msgstr "" msgid "Download image from URL" msgstr "" -#: company/templates/company/company_base.html:46 order/views.py:306 +#: company/templates/company/company_base.html:46 order/views.py:311 msgid "Create Purchase Order" msgstr "" @@ -2022,8 +2154,7 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "" -"There are %(count)s parts sourced from this company.
    \n" +msgid "There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2039,10 +2170,11 @@ msgstr "" msgid "Uses default currency" msgstr "" -#: company/templates/company/detail.html:67 order/models.py:450 -#: order/templates/order/sales_order_base.html:92 stock/models.py:415 -#: stock/models.py:416 stock/templates/stock/item_base.html:251 +#: company/templates/company/detail.html:67 order/models.py:461 +#: order/templates/order/sales_order_base.html:92 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:257 #: templates/js/company.js:40 templates/js/order.js:267 +#: templates/js/stock.js:1064 msgid "Customer" msgstr "" @@ -2088,7 +2220,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1157 +#: templates/js/stock.js:1279 msgid "New Part" msgstr "" @@ -2135,19 +2267,19 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1163 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_supplier_part.html:72 #: company/templates/company/manufacturer_part_suppliers.html:47 -#: company/views.py:64 order/templates/order/purchase_orders.html:183 +#: company/views.py:64 order/templates/order/purchase_orders.html:185 #: part/templates/part/supplier.html:50 msgid "New Supplier" msgstr "" #: company/templates/company/detail_supplier_part.html:73 company/views.py:281 -#: order/templates/order/purchase_orders.html:184 +#: order/templates/order/purchase_orders.html:186 msgid "Create new Supplier" msgstr "" @@ -2205,7 +2337,7 @@ msgstr "" #: company/templates/company/manufacturer_part_navbar.html:22 #: company/templates/company/navbar.html:41 #: company/templates/company/supplier_part_navbar.html:15 -#: part/templates/part/navbar.html:36 stock/api.py:51 +#: part/templates/part/navbar.html:36 stock/api.py:54 #: stock/templates/stock/loc_link.html:7 stock/templates/stock/location.html:36 #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 @@ -2258,7 +2390,7 @@ msgstr "" #: stock/templates/stock/location_navbar.html:22 #: stock/templates/stock/location_navbar.html:29 #: templates/InvenTree/search.html:198 templates/js/stock.js:968 -#: templates/stats.html:72 templates/stats.html:81 users/models.py:42 +#: templates/stats.html:93 templates/stats.html:102 users/models.py:42 msgid "Stock Items" msgstr "" @@ -2313,8 +2445,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:7 -#: company/templates/company/supplier_part_base.html:20 stock/models.py:382 -#: stock/templates/stock/item_base.html:358 templates/js/company.js:279 +#: company/templates/company/supplier_part_base.html:20 stock/models.py:414 +#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2363,7 +2495,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2636 +#: part/templates/part/sale_prices.html:17 part/views.py:2644 msgid "Add Price Break" msgstr "" @@ -2393,7 +2525,7 @@ msgstr "" msgid "Customers" msgstr "" -#: company/views.py:78 order/templates/order/sales_orders.html:185 +#: company/views.py:78 order/templates/order/sales_orders.html:187 msgid "New Customer" msgstr "" @@ -2413,6 +2545,11 @@ msgstr "" msgid "Image size exceeds maximum allowable size for download" msgstr "" +#: company/views.py:205 part/views.py:887 +#, python-brace-format +msgid "Invalid response: {code}" +msgstr "" + #: company/views.py:214 part/views.py:896 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2433,7 +2570,7 @@ msgstr "" msgid "Edited company information" msgstr "" -#: company/views.py:287 order/templates/order/sales_orders.html:186 +#: company/views.py:287 order/templates/order/sales_orders.html:188 msgid "Create new Customer" msgstr "" @@ -2465,7 +2602,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1164 +#: company/views.py:578 templates/js/stock.js:1286 msgid "Create new Supplier Part" msgstr "" @@ -2473,15 +2610,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2640 +#: company/views.py:799 part/views.py:2648 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2684 +#: company/views.py:855 part/views.py:2692 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2698 +#: company/views.py:870 part/views.py:2706 msgid "Delete Price Break" msgstr "" @@ -2489,51 +2626,59 @@ msgstr "" msgid "No valid objects provided to template" msgstr "" -#: label/models.py:102 +#: label/models.py:103 msgid "Label name" msgstr "" -#: label/models.py:109 +#: label/models.py:110 msgid "Label description" msgstr "" -#: label/models.py:116 stock/forms.py:202 +#: label/models.py:117 stock/forms.py:202 msgid "Label" msgstr "" -#: label/models.py:117 +#: label/models.py:118 msgid "Label template file" msgstr "" -#: label/models.py:123 report/models.py:274 +#: label/models.py:124 report/models.py:274 msgid "Enabled" msgstr "" -#: label/models.py:124 +#: label/models.py:125 msgid "Label template is enabled" msgstr "" -#: label/models.py:129 +#: label/models.py:130 msgid "Width [mm]" msgstr "" -#: label/models.py:130 +#: label/models.py:131 msgid "Label width, specified in mm" msgstr "" -#: label/models.py:136 +#: label/models.py:137 msgid "Height [mm]" msgstr "" -#: label/models.py:137 +#: label/models.py:138 msgid "Label height, specified in mm" msgstr "" -#: label/models.py:222 label/models.py:275 +#: label/models.py:144 +msgid "Filename Pattern" +msgstr "" + +#: label/models.py:145 +msgid "Pattern for generating label filenames" +msgstr "" + +#: label/models.py:244 label/models.py:297 msgid "Query filters (comma-separated list of key=value pairs" msgstr "" -#: label/models.py:223 label/models.py:276 report/models.py:294 +#: label/models.py:245 label/models.py:298 report/models.py:294 #: report/models.py:415 report/models.py:449 msgid "Filters" msgstr "" @@ -2571,15 +2716,15 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:145 order/models.py:462 +#: order/forms.py:145 order/models.py:473 msgid "Target date for order completion. Order will be overdue after this date." msgstr "" -#: order/forms.py:235 +#: order/forms.py:236 msgid "Enter stock item serial numbers" msgstr "" -#: order/forms.py:241 +#: order/forms.py:242 msgid "Enter quantity of stock items" msgstr "" @@ -2607,7 +2752,7 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:182 order/models.py:455 +#: order/models.py:182 order/models.py:466 msgid "Purchase order status" msgstr "" @@ -2648,8 +2793,8 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:270 -#: stock/models.py:953 +#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2657,128 +2802,134 @@ msgstr "" msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:344 +#: order/models.py:346 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:348 +#: order/models.py:350 msgid "Quantity must be an integer" msgstr "" -#: order/models.py:350 +#: order/models.py:352 msgid "Quantity must be a positive number" msgstr "" -#: order/models.py:369 -msgid "Received items" -msgstr "" - -#: order/models.py:451 +#: order/models.py:462 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer Reference " msgstr "" -#: order/models.py:457 +#: order/models.py:468 msgid "Customer order reference code" msgstr "" -#: order/models.py:465 templates/js/order.js:303 +#: order/models.py:476 templates/js/order.js:303 msgid "Shipment Date" msgstr "" -#: order/models.py:472 +#: order/models.py:483 msgid "shipped by" msgstr "" -#: order/models.py:516 +#: order/models.py:527 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:603 +#: order/models.py:614 msgid "Item quantity" msgstr "" -#: order/models.py:605 +#: order/models.py:616 msgid "Line item reference" msgstr "" -#: order/models.py:607 +#: order/models.py:618 msgid "Line item notes" msgstr "" -#: order/models.py:633 order/models.py:677 +#: order/models.py:644 order/models.py:689 #: part/templates/part/allocation.html:17 #: part/templates/part/allocation.html:45 msgid "Order" msgstr "" -#: order/models.py:634 order/templates/order/order_base.html:9 +#: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:313 templates/js/order.js:148 +#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 +#: templates/js/stock.js:1045 msgid "Purchase Order" msgstr "" -#: order/models.py:648 +#: order/models.py:659 msgid "Supplier part" msgstr "" -#: order/models.py:651 order/templates/order/order_base.html:131 +#: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 #: order/templates/order/sales_order_base.html:131 msgid "Received" msgstr "" -#: order/models.py:651 +#: order/models.py:662 msgid "Number of items received" msgstr "" -#: order/models.py:658 stock/models.py:508 -#: stock/templates/stock/item_base.html:320 +#: order/models.py:669 stock/models.py:540 +#: stock/templates/stock/item_base.html:326 msgid "Purchase Price" msgstr "" -#: order/models.py:659 +#: order/models.py:670 msgid "Unit purchase price" msgstr "" -#: order/models.py:753 order/models.py:755 +#: order/models.py:698 part/templates/part/navbar.html:95 +#: part/templates/part/part_pricing.html:78 +msgid "Sale Price" +msgstr "" + +#: order/models.py:699 +msgid "Unit sale price" +msgstr "" + +#: order/models.py:774 order/models.py:776 msgid "Stock item has not been assigned" msgstr "" -#: order/models.py:759 +#: order/models.py:780 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:761 +#: order/models.py:782 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:764 +#: order/models.py:785 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:774 +#: order/models.py:795 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:779 +#: order/models.py:800 msgid "Line" msgstr "" -#: order/models.py:790 +#: order/models.py:811 msgid "Item" msgstr "" -#: order/models.py:791 +#: order/models.py:812 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:794 +#: order/models.py:815 msgid "Enter stock allocation quantity" msgstr "" @@ -2830,7 +2981,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1169 +#: templates/js/stock.js:1291 msgid "New Location" msgstr "" @@ -2864,6 +3015,75 @@ msgstr "" msgid "Order Notes" msgstr "" +#: order/templates/order/order_wizard/match_fields.html:9 +#: part/templates/part/bom_upload/select_fields.html:21 +msgid "Missing selections for the following required columns" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:20 +msgid "Duplicate selections found, see below. Fix them then retry submitting." +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:27 +#: order/templates/order/order_wizard/match_parts.html:18 +#: order/templates/order/order_wizard/po_upload.html:40 +msgid "Previous Step" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:29 +#: order/templates/order/order_wizard/match_parts.html:20 +#: part/templates/part/bom_upload/select_fields.html:32 +msgid "Submit Selections" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:35 +#: part/templates/part/bom_upload/select_fields.html:41 +msgid "File Fields" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:42 +#: part/templates/part/bom_upload/select_fields.html:47 +msgid "Remove column" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:60 +msgid "Duplicate selection" +msgstr "" + +#: order/templates/order/order_wizard/match_fields.html:71 +#: order/templates/order/order_wizard/match_parts.html:51 +#: part/templates/part/bom_upload/select_fields.html:76 +#: part/templates/part/bom_upload/select_parts.html:58 +msgid "Remove row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:11 +#: part/templates/part/bom_upload/select_parts.html:21 +msgid "Errors exist in the submitted data" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:27 +#: part/templates/part/bom_upload/select_parts.html:39 +msgid "Row" +msgstr "" + +#: order/templates/order/order_wizard/match_parts.html:28 +msgid "Select Supplier Part" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:11 +msgid "Upload File for Purchase Order" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:18 +#, python-format +msgid "Step %(step)s of %(count)s" +msgstr "" + +#: order/templates/order/order_wizard/po_upload.html:48 +msgid "Order is already processed. Files cannot be uploaded." +msgstr "" + #: order/templates/order/order_wizard/select_parts.html:9 msgid "Step 1 of 2 - Select Part Suppliers" msgstr "" @@ -2936,8 +3156,8 @@ msgid "Purchase Order Items" msgstr "" #: order/templates/order/purchase_order_detail.html:24 -#: order/templates/order/sales_order_detail.html:22 order/views.py:1120 -#: order/views.py:1203 +#: order/templates/order/sales_order_detail.html:22 order/views.py:1311 +#: order/views.py:1394 msgid "Add Line Item" msgstr "" @@ -2946,11 +3166,12 @@ msgid "No line items found" msgstr "" #: order/templates/order/purchase_order_detail.html:180 +#: order/templates/order/sales_order_detail.html:235 msgid "Unit Price" msgstr "" #: order/templates/order/purchase_order_detail.html:221 -#: order/templates/order/sales_order_detail.html:294 +#: order/templates/order/sales_order_detail.html:328 msgid "Edit line item" msgstr "" @@ -2980,7 +3201,7 @@ msgstr "" #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 #: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 -#: templates/navbar.html:23 templates/stats.html:59 templates/stats.html:68 +#: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" msgstr "" @@ -3042,59 +3263,72 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:92 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" -#: order/templates/order/sales_order_detail.html:99 templates/js/build.js:515 +#: order/templates/order/sales_order_detail.html:102 templates/js/build.js:515 #: templates/js/build.js:849 msgid "Edit stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:100 templates/js/build.js:517 +#: order/templates/order/sales_order_detail.html:103 templates/js/build.js:517 #: templates/js/build.js:850 msgid "Delete stock allocation" msgstr "" -#: order/templates/order/sales_order_detail.html:170 +#: order/templates/order/sales_order_detail.html:176 msgid "No matching line items" msgstr "" -#: order/templates/order/sales_order_detail.html:199 +#: order/templates/order/sales_order_detail.html:205 msgid "ID" msgstr "" -#: order/templates/order/sales_order_detail.html:229 templates/js/build.js:579 +#: order/templates/order/sales_order_detail.html:243 templates/js/build.js:579 #: templates/js/build.js:845 msgid "Allocated" msgstr "" -#: order/templates/order/sales_order_detail.html:231 +#: order/templates/order/sales_order_detail.html:245 msgid "Fulfilled" msgstr "" -#: order/templates/order/sales_order_detail.html:279 +#: order/templates/order/sales_order_detail.html:282 +msgid "PO" +msgstr "" + +#: order/templates/order/sales_order_detail.html:312 msgid "Allocate serial numbers" msgstr "" -#: order/templates/order/sales_order_detail.html:282 templates/js/build.js:641 +#: order/templates/order/sales_order_detail.html:315 templates/js/build.js:641 msgid "Allocate stock" msgstr "" -#: order/templates/order/sales_order_detail.html:285 +#: order/templates/order/sales_order_detail.html:318 msgid "Purchase stock" msgstr "" -#: order/templates/order/sales_order_detail.html:289 templates/js/build.js:634 +#: order/templates/order/sales_order_detail.html:322 templates/js/build.js:634 #: templates/js/build.js:1052 msgid "Build stock" msgstr "" -#: order/templates/order/sales_order_detail.html:295 +#: order/templates/order/sales_order_detail.html:325 +#: order/templates/order/sales_order_detail.html:434 +msgid "Calculate price" +msgstr "" + +#: order/templates/order/sales_order_detail.html:329 msgid "Delete line item " msgstr "" +#: order/templates/order/sales_order_detail.html:440 +msgid "Update Unit Price" +msgstr "" + #: order/templates/order/sales_order_notes.html:14 msgid "Sales Order Notes" msgstr "" @@ -3136,164 +3370,189 @@ msgstr "" msgid "Are you sure you wish to delete this line item?" msgstr "" -#: order/views.py:99 +#: order/views.py:104 msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:149 +#: order/views.py:154 msgid "Add Sales Order Attachment" msgstr "" -#: order/views.py:341 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:376 +#: order/views.py:381 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:396 +#: order/views.py:401 msgid "Edit Sales Order" msgstr "" -#: order/views.py:412 +#: order/views.py:417 msgid "Cancel Order" msgstr "" -#: order/views.py:421 order/views.py:447 +#: order/views.py:426 order/views.py:452 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:424 order/views.py:450 +#: order/views.py:429 order/views.py:455 msgid "Order cannot be cancelled" msgstr "" -#: order/views.py:438 +#: order/views.py:443 msgid "Cancel sales order" msgstr "" -#: order/views.py:464 +#: order/views.py:469 msgid "Issue Order" msgstr "" -#: order/views.py:473 +#: order/views.py:478 msgid "Confirm order placement" msgstr "" -#: order/views.py:483 +#: order/views.py:488 msgid "Purchase order issued" msgstr "" -#: order/views.py:494 +#: order/views.py:499 msgid "Complete Order" msgstr "" -#: order/views.py:510 +#: order/views.py:515 msgid "Confirm order completion" msgstr "" -#: order/views.py:521 +#: order/views.py:526 msgid "Purchase order completed" msgstr "" -#: order/views.py:531 +#: order/views.py:536 msgid "Ship Order" msgstr "" -#: order/views.py:547 +#: order/views.py:552 msgid "Confirm order shipment" msgstr "" -#: order/views.py:553 +#: order/views.py:558 msgid "Could not ship order" msgstr "" -#: order/views.py:607 +#: order/views.py:584 +msgid "Match Supplier Parts" +msgstr "" + +#: order/views.py:798 msgid "Receive Parts" msgstr "" -#: order/views.py:677 +#: order/views.py:868 msgid "Items received" msgstr "" -#: order/views.py:691 +#: order/views.py:882 msgid "No destination set" msgstr "" -#: order/views.py:736 +#: order/views.py:927 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:742 +#: order/views.py:933 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:748 +#: order/views.py:939 msgid "No lines specified" msgstr "" -#: order/views.py:1069 +#: order/views.py:1260 #, python-brace-format msgid "Ordered {n} parts" msgstr "" -#: order/views.py:1129 +#: order/views.py:1320 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1135 +#: order/views.py:1326 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1254 order/views.py:1272 +#: order/views.py:1457 order/views.py:1475 msgid "Edit Line Item" msgstr "" -#: order/views.py:1288 order/views.py:1300 +#: order/views.py:1491 order/views.py:1503 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1305 +#: order/views.py:1496 order/views.py:1508 msgid "Deleted line item" msgstr "" -#: order/views.py:1318 +#: order/views.py:1521 msgid "Allocate Serial Numbers" msgstr "" -#: order/views.py:1363 +#: order/views.py:1566 #, python-brace-format msgid "Allocated {n} items" msgstr "" -#: order/views.py:1379 +#: order/views.py:1582 msgid "Select line item" msgstr "" -#: order/views.py:1410 -msgid "No matching item for serial" +#: order/views.py:1613 +#, python-brace-format +msgid "No matching item for serial {serial}" msgstr "" -#: order/views.py:1420 -msgid "is not in stock" +#: order/views.py:1623 +#, python-brace-format +msgid "{serial} is not in stock" msgstr "" -#: order/views.py:1428 -msgid "already allocated to an order" +#: order/views.py:1631 +#, python-brace-format +msgid "{serial} already allocated to an order" msgstr "" -#: order/views.py:1482 +#: order/views.py:1685 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1556 +#: order/views.py:1759 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1571 +#: order/views.py:1774 msgid "Remove allocation" msgstr "" +#: order/views.py:1846 +msgid "Sales order not found" +msgstr "" + +#: order/views.py:1852 +msgid "Price not found" +msgstr "" + +#: order/views.py:1855 +#, python-brace-format +msgid "Updated {part} unit-price to {price}" +msgstr "" + +#: order/views.py:1860 +#, python-brace-format +msgid "Updated {part} unit-price to {price} and quantity to {qty}" +msgstr "" + #: part/bom.py:138 part/models.py:72 part/models.py:762 #: part/templates/part/category.html:66 part/templates/part/detail.html:90 msgid "Default Location" @@ -3372,7 +3631,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2077 +#: part/forms.py:122 part/models.py:2115 msgid "Parent Part" msgstr "" @@ -3448,7 +3707,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2171 +#: part/forms.py:344 part/models.py:2209 msgid "Sub part" msgstr "" @@ -3468,14 +3727,14 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2123 +#: part/models.py:82 part/models.py:2161 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" #: part/models.py:83 part/templates/part/category.html:23 #: part/templates/part/category.html:94 part/templates/part/category.html:141 -#: templates/InvenTree/search.html:127 templates/stats.html:63 +#: templates/InvenTree/search.html:127 templates/stats.html:84 #: users/models.py:39 msgid "Part Categories" msgstr "" @@ -3538,7 +3797,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2122 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3593,7 +3852,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2051 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3623,8 +3882,8 @@ msgid "Can this part be sold to customers?" msgstr "" #: part/models.py:861 part/templates/part/detail.html:227 -#: templates/js/table_filters.js:20 templates/js/table_filters.js:60 -#: templates/js/table_filters.js:236 templates/js/table_filters.js:305 +#: templates/js/table_filters.js:21 templates/js/table_filters.js:61 +#: templates/js/table_filters.js:237 templates/js/table_filters.js:306 msgid "Active" msgstr "" @@ -3660,167 +3919,171 @@ msgstr "" msgid "Creation User" msgstr "" -#: part/models.py:1949 -msgid "Test templates can only be created for trackable parts" -msgstr "" - -#: part/models.py:1966 -msgid "Test with this name already exists for this part" -msgstr "" - -#: part/models.py:1986 templates/js/part.js:638 templates/js/stock.js:104 -msgid "Test Name" +#: part/models.py:1616 +msgid "Sell multiple" msgstr "" #: part/models.py:1987 +msgid "Test templates can only be created for trackable parts" +msgstr "" + +#: part/models.py:2004 +msgid "Test with this name already exists for this part" +msgstr "" + +#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +msgid "Test Name" +msgstr "" + +#: part/models.py:2025 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1992 +#: part/models.py:2030 msgid "Test Description" msgstr "" -#: part/models.py:1993 +#: part/models.py:2031 msgid "Enter description for this test" msgstr "" -#: part/models.py:1998 templates/js/part.js:647 -#: templates/js/table_filters.js:222 +#: part/models.py:2036 templates/js/part.js:647 +#: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:1999 +#: part/models.py:2037 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2004 templates/js/part.js:655 +#: part/models.py:2042 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2005 +#: part/models.py:2043 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2010 templates/js/part.js:662 +#: part/models.py:2048 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2011 +#: part/models.py:2049 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2044 +#: part/models.py:2082 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2049 +#: part/models.py:2087 msgid "Parameter Name" msgstr "" -#: part/models.py:2051 +#: part/models.py:2089 msgid "Parameter Units" msgstr "" -#: part/models.py:2079 part/models.py:2128 part/models.py:2129 +#: part/models.py:2117 part/models.py:2166 part/models.py:2167 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Data" msgstr "" -#: part/models.py:2081 +#: part/models.py:2119 msgid "Parameter Value" msgstr "" -#: part/models.py:2133 templates/InvenTree/settings/category.html:67 +#: part/models.py:2171 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2134 +#: part/models.py:2172 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2163 +#: part/models.py:2201 msgid "Select parent part" msgstr "" -#: part/models.py:2172 +#: part/models.py:2210 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2178 +#: part/models.py:2216 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2180 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 msgid "Optional" msgstr "" -#: part/models.py:2180 +#: part/models.py:2218 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2183 +#: part/models.py:2221 msgid "Overage" msgstr "" -#: part/models.py:2184 +#: part/models.py:2222 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2187 +#: part/models.py:2225 msgid "BOM item reference" msgstr "" -#: part/models.py:2190 +#: part/models.py:2228 msgid "BOM item notes" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "Checksum" msgstr "" -#: part/models.py:2192 +#: part/models.py:2230 msgid "BOM line checksum" msgstr "" -#: part/models.py:2196 templates/js/bom.js:279 templates/js/bom.js:286 -#: templates/js/table_filters.js:50 +#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2197 +#: part/models.py:2235 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2273 part/views.py:1592 part/views.py:1644 -#: stock/models.py:260 +#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2282 part/models.py:2284 +#: part/models.py:2320 part/models.py:2322 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2287 +#: part/models.py:2325 msgid "BOM Item" msgstr "" -#: part/models.py:2404 +#: part/models.py:2442 msgid "Part 1" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Part 2" msgstr "" -#: part/models.py:2408 +#: part/models.py:2446 msgid "Select Related Part" msgstr "" -#: part/models.py:2440 +#: part/models.py:2478 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -3905,7 +4168,7 @@ msgid "All selected BOM items will be deleted" msgstr "" #: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1158 +#: templates/js/stock.js:1280 msgid "Create New Part" msgstr "" @@ -3923,51 +4186,18 @@ msgstr "" msgid "Step 2 - Select Fields" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:21 -msgid "Missing selections for the following required columns" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:32 -msgid "Submit Selections" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:41 -msgid "File Fields" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:47 -msgid "Remove column" -msgstr "" - -#: part/templates/part/bom_upload/select_fields.html:58 -msgid "Match Fields" -msgstr "" - #: part/templates/part/bom_upload/select_fields.html:68 msgid "Duplicate column selection" msgstr "" -#: part/templates/part/bom_upload/select_fields.html:76 -#: part/templates/part/bom_upload/select_parts.html:58 -msgid "Remove row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:16 msgid "Step 3 - Select Parts" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:21 -msgid "Errors exist in the submitted data" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:27 msgid "Submit BOM" msgstr "" -#: part/templates/part/bom_upload/select_parts.html:39 -msgid "Row" -msgstr "" - #: part/templates/part/bom_upload/select_parts.html:40 #: part/templates/part/bom_upload/select_parts.html:69 msgid "Select Part" @@ -3998,10 +4228,6 @@ msgstr "" msgid "Each part must already exist in the database" msgstr "" -#: part/templates/part/bom_upload/upload_file.html:27 -msgid "Upload File" -msgstr "" - #: part/templates/part/bom_validate.html:6 #, python-format msgid "Confirm that the Bill of Materials (BOM) is valid for:
    %(part)s" @@ -4023,7 +4249,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2282 +#: part/templates/part/category.html:29 part/views.py:2290 msgid "Create new part category" msgstr "" @@ -4091,7 +4317,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:228 stock/views.py:1359 +#: part/templates/part/category.html:228 stock/views.py:1391 msgid "Create new Stock Location" msgstr "" @@ -4282,15 +4508,11 @@ msgstr "" msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:95 -msgid "Sale Price" -msgstr "" - #: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:398 +#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 msgid "Tests" msgstr "" @@ -4315,7 +4537,7 @@ msgstr "" #: part/templates/part/params.html:28 #: report/templates/report/inventree_test_report_base.html:90 -#: stock/models.py:1655 templates/InvenTree/settings/header.html:8 +#: stock/models.py:1754 templates/InvenTree/settings/header.html:8 #: templates/js/stock.js:124 msgid "Value" msgstr "" @@ -4351,19 +4573,19 @@ msgid "Star this part" msgstr "" #: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:131 +#: stock/templates/stock/item_base.html:137 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" #: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:139 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" #: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:149 +#: stock/templates/stock/item_base.html:155 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" @@ -4392,7 +4614,7 @@ msgstr "" msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:156 +#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" @@ -4420,42 +4642,39 @@ msgstr "" msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:8 -#, python-format -msgid "Pricing information for:
    %(part)s." -msgstr "" - -#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:19 msgid "Supplier Pricing" msgstr "" -#: part/templates/part/part_pricing.html:27 -#: part/templates/part/part_pricing.html:53 +#: part/templates/part/part_pricing.html:23 +#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:81 msgid "Unit Cost" msgstr "" -#: part/templates/part/part_pricing.html:33 -#: part/templates/part/part_pricing.html:59 +#: part/templates/part/part_pricing.html:29 +#: part/templates/part/part_pricing.html:55 +#: part/templates/part/part_pricing.html:85 msgid "Total Cost" msgstr "" -#: part/templates/part/part_pricing.html:41 +#: part/templates/part/part_pricing.html:37 msgid "No supplier pricing available" msgstr "" -#: part/templates/part/part_pricing.html:49 +#: part/templates/part/part_pricing.html:45 msgid "BOM Pricing" msgstr "" -#: part/templates/part/part_pricing.html:67 +#: part/templates/part/part_pricing.html:63 msgid "Note: BOM pricing is incomplete for this part" msgstr "" -#: part/templates/part/part_pricing.html:74 +#: part/templates/part/part_pricing.html:70 msgid "No BOM pricing available" msgstr "" -#: part/templates/part/part_pricing.html:84 +#: part/templates/part/part_pricing.html:94 msgid "No pricing information is available for this part." msgstr "" @@ -4564,6 +4783,10 @@ msgstr "" msgid "New Variant" msgstr "" +#: part/templatetags/inventree_extras.py:97 +msgid "Unknown database" +msgstr "" + #: part/views.py:89 msgid "Add Related Part" msgstr "" @@ -4713,63 +4936,63 @@ msgstr "" msgid "Part Pricing" msgstr "" -#: part/views.py:2081 +#: part/views.py:2089 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2091 +#: part/views.py:2099 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2098 +#: part/views.py:2106 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2114 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2156 +#: part/views.py:2164 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2170 +#: part/views.py:2178 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2230 +#: part/views.py:2238 msgid "Edit Part Category" msgstr "" -#: part/views.py:2268 +#: part/views.py:2276 msgid "Delete Part Category" msgstr "" -#: part/views.py:2274 +#: part/views.py:2282 msgid "Part category was deleted" msgstr "" -#: part/views.py:2326 +#: part/views.py:2334 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2427 +#: part/views.py:2435 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2483 +#: part/views.py:2491 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2502 +#: part/views.py:2510 msgid "Create BOM Item" msgstr "" -#: part/views.py:2572 +#: part/views.py:2580 msgid "Edit BOM item" msgstr "" -#: part/views.py:2628 +#: part/views.py:2636 msgid "Confim BOM item deletion" msgstr "" @@ -4871,17 +5094,17 @@ msgid "Test Results" msgstr "" #: report/templates/report/inventree_test_report_base.html:88 -#: stock/models.py:1643 +#: stock/models.py:1742 msgid "Test" msgstr "" #: report/templates/report/inventree_test_report_base.html:89 -#: stock/models.py:1649 +#: stock/models.py:1748 msgid "Result" msgstr "" #: report/templates/report/inventree_test_report_base.html:92 -#: templates/js/order.js:195 templates/js/stock.js:986 +#: templates/js/order.js:195 templates/js/stock.js:984 msgid "Date" msgstr "" @@ -4893,22 +5116,22 @@ msgstr "" msgid "Fail" msgstr "" -#: stock/api.py:199 +#: stock/api.py:212 #, python-brace-format msgid "Updated stock for {n} items" msgstr "" -#: stock/api.py:268 +#: stock/api.py:281 #, python-brace-format msgid "Moved {n} parts to {loc}" msgstr "" -#: stock/forms.py:114 stock/forms.py:406 stock/models.py:475 -#: stock/templates/stock/item_base.html:365 templates/js/stock.js:656 +#: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 +#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" -#: stock/forms.py:115 stock/forms.py:407 +#: stock/forms.py:115 stock/forms.py:419 msgid "Expiration date for this stock item" msgstr "" @@ -4936,8 +5159,8 @@ msgstr "" msgid "Select test report template" msgstr "" -#: stock/forms.py:267 templates/js/table_filters.js:70 -#: templates/js/table_filters.js:133 +#: stock/forms.py:267 templates/js/table_filters.js:71 +#: templates/js/table_filters.js:134 msgid "Include sublocations" msgstr "" @@ -4993,243 +5216,187 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:54 stock/models.py:513 +#: stock/models.py:54 stock/models.py:545 msgid "Owner" msgstr "" -#: stock/models.py:55 stock/models.py:514 +#: stock/models.py:55 stock/models.py:546 msgid "Select Owner" msgstr "" -#: stock/models.py:205 -msgid "Created stock item" -msgstr "" - -#: stock/models.py:241 +#: stock/models.py:273 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:277 +#: stock/models.py:309 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:287 stock/models.py:296 +#: stock/models.py:319 stock/models.py:328 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:288 +#: stock/models.py:320 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:310 +#: stock/models.py:342 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:316 +#: stock/models.py:348 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:323 +#: stock/models.py:355 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:365 +#: stock/models.py:397 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:374 +#: stock/models.py:406 msgid "Base part" msgstr "" -#: stock/models.py:383 +#: stock/models.py:415 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:388 stock/templates/stock/stock_app_base.html:8 +#: stock/models.py:420 stock/templates/stock/stock_app_base.html:8 msgid "Stock Location" msgstr "" -#: stock/models.py:391 +#: stock/models.py:423 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:398 +#: stock/models.py:430 msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:403 stock/templates/stock/item_base.html:259 +#: stock/models.py:435 stock/templates/stock/item_base.html:265 msgid "Installed In" msgstr "" -#: stock/models.py:406 +#: stock/models.py:438 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:422 +#: stock/models.py:454 msgid "Serial number for this item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:466 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:438 +#: stock/models.py:470 msgid "Stock Quantity" msgstr "" -#: stock/models.py:447 +#: stock/models.py:479 msgid "Source Build" msgstr "" -#: stock/models.py:449 +#: stock/models.py:481 msgid "Build for this stock item" msgstr "" -#: stock/models.py:460 +#: stock/models.py:492 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:463 +#: stock/models.py:495 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:469 +#: stock/models.py:501 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:476 +#: stock/models.py:508 msgid "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete on deplete" msgstr "" -#: stock/models.py:489 +#: stock/models.py:521 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:499 stock/templates/stock/item_notes.html:13 +#: stock/models.py:531 stock/templates/stock/item_notes.html:13 #: stock/templates/stock/navbar.html:54 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:509 +#: stock/models.py:541 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:614 -msgid "Assigned to Customer" -msgstr "" - -#: stock/models.py:616 -msgid "Manually assigned to customer" -msgstr "" - -#: stock/models.py:629 -msgid "Returned from customer" -msgstr "" - -#: stock/models.py:631 -msgid "Returned to location" -msgstr "" - -#: stock/models.py:792 -msgid "Installed into stock item" -msgstr "" - -#: stock/models.py:800 -msgid "Installed stock item" -msgstr "" - -#: stock/models.py:824 -msgid "Uninstalled stock item" -msgstr "" - -#: stock/models.py:843 -msgid "Uninstalled into location" -msgstr "" - -#: stock/models.py:944 +#: stock/models.py:1009 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:950 +#: stock/models.py:1015 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:956 +#: stock/models.py:1021 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:959 +#: stock/models.py:1024 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:962 +#: stock/models.py:1027 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:994 -msgid "Add serial number" -msgstr "" - -#: stock/models.py:997 +#: stock/models.py:1034 #, python-brace-format -msgid "Serialized {n} items" +msgid "Serial numbers already exist: {exists}" msgstr "" -#: stock/models.py:1075 -msgid "Split from existing stock" -msgstr "" - -#: stock/models.py:1113 +#: stock/models.py:1192 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1556 -msgid "Title" -msgstr "" - -#: stock/models.py:1556 -msgid "Tracking entry title" -msgstr "" - -#: stock/models.py:1558 +#: stock/models.py:1666 msgid "Entry notes" msgstr "" -#: stock/models.py:1560 -msgid "Link to external page for further information" -msgstr "" - -#: stock/models.py:1620 +#: stock/models.py:1719 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1626 +#: stock/models.py:1725 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1644 +#: stock/models.py:1743 msgid "Test name" msgstr "" -#: stock/models.py:1650 templates/js/table_filters.js:212 +#: stock/models.py:1749 templates/js/table_filters.js:213 msgid "Test result" msgstr "" -#: stock/models.py:1656 +#: stock/models.py:1755 msgid "Test output value" msgstr "" -#: stock/models.py:1663 +#: stock/models.py:1762 msgid "Test result attachment" msgstr "" -#: stock/models.py:1669 +#: stock/models.py:1768 msgid "Test notes" msgstr "" @@ -5284,134 +5451,134 @@ msgid "This stock item will be automatically deleted when all stock is depleted. msgstr "" #: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:369 templates/js/table_filters.js:145 +#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:99 -#: stock/templates/stock/item_base.html:371 templates/js/table_filters.js:150 +#: stock/templates/stock/item_base.html:105 +#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:136 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:138 +#: stock/templates/stock/item_base.html:144 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:140 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:147 +#: stock/templates/stock/item_base.html:153 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:151 +#: stock/templates/stock/item_base.html:157 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:160 +#: stock/templates/stock/item_base.html:166 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:164 +#: stock/templates/stock/item_base.html:170 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:167 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:170 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:173 +#: stock/templates/stock/item_base.html:179 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:177 +#: stock/templates/stock/item_base.html:183 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:180 +#: stock/templates/stock/item_base.html:186 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:189 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:187 templates/js/stock.js:1299 +#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:187 +#: stock/templates/stock/item_base.html:193 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:196 +#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:199 +#: stock/templates/stock/item_base.html:205 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:208 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:204 +#: stock/templates/stock/item_base.html:210 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:207 +#: stock/templates/stock/item_base.html:213 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:219 +#: stock/templates/stock/item_base.html:225 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:278 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:285 +#: stock/templates/stock/item_base.html:291 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:327 +#: stock/templates/stock/item_base.html:333 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:369 +#: stock/templates/stock/item_base.html:375 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:371 +#: stock/templates/stock/item_base.html:377 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:378 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:383 +#: stock/templates/stock/item_base.html:389 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:387 +#: stock/templates/stock/item_base.html:393 msgid "No stocktake performed" msgstr "" @@ -5522,7 +5689,7 @@ msgid "Stock Details" msgstr "" #: stock/templates/stock/location.html:117 templates/InvenTree/search.html:279 -#: templates/stats.html:76 users/models.py:41 +#: templates/stats.html:97 users/models.py:41 msgid "Stock Locations" msgstr "" @@ -5562,7 +5729,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1332 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1364 msgid "Convert Stock Item" msgstr "" @@ -5595,8 +5762,8 @@ msgstr "" msgid "Edit Stock Location" msgstr "" -#: stock/views.py:230 stock/views.py:1322 stock/views.py:1433 -#: stock/views.py:1798 +#: stock/views.py:230 stock/views.py:1343 stock/views.py:1465 +#: stock/views.py:1830 msgid "Owner is required (ownership control is enabled)" msgstr "" @@ -5762,43 +5929,47 @@ msgstr "" msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1224 +#: stock/views.py:1222 +msgid "Edit Stock Item Status" +msgstr "" + +#: stock/views.py:1245 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1450 +#: stock/views.py:1482 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1543 templates/js/build.js:244 +#: stock/views.py:1575 templates/js/build.js:244 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1685 +#: stock/views.py:1717 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1767 +#: stock/views.py:1799 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1867 +#: stock/views.py:1899 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1880 +#: stock/views.py:1912 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1891 +#: stock/views.py:1923 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1898 +#: stock/views.py:1930 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1907 +#: stock/views.py:1939 msgid "Add Stock Tracking Entry" msgstr "" @@ -5896,8 +6067,7 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "" -"\n" +msgid "\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6100,9 +6270,17 @@ msgstr "" msgid "Submit Bug Report" msgstr "" -#: templates/about.html:82 templates/js/modals.js:550 -#: templates/js/modals.js:809 templates/modals.html:28 templates/modals.html:52 -#: templates/modals.html:93 +#: templates/about.html:80 templates/clip.html:4 +msgid "copy to clipboard" +msgstr "" + +#: templates/about.html:80 +msgid "copy version information" +msgstr "" + +#: templates/about.html:90 templates/js/modals.js:568 +#: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 +#: templates/modals.html:97 msgid "Close" msgstr "" @@ -6110,10 +6288,6 @@ msgstr "" msgid "Add Attachment" msgstr "" -#: templates/attachment_table.html:15 -msgid "File" -msgstr "" - #: templates/attachment_table.html:17 msgid "Uploaded" msgstr "" @@ -6166,7 +6340,7 @@ msgstr "" msgid "Unknown response from server" msgstr "" -#: templates/js/barcode.js:119 templates/js/modals.js:857 +#: templates/js/barcode.js:119 templates/js/modals.js:901 msgid "Invalid server response" msgstr "" @@ -6311,7 +6485,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1331 +#: templates/js/stock.js:1453 msgid "Select" msgstr "" @@ -6409,96 +6583,96 @@ msgstr "" msgid "Select Label Template" msgstr "" -#: templates/js/modals.js:256 +#: templates/js/modals.js:265 msgid "Waiting for server..." msgstr "" -#: templates/js/modals.js:406 +#: templates/js/modals.js:424 msgid "Show Error Information" msgstr "" -#: templates/js/modals.js:473 templates/modals.html:73 +#: templates/js/modals.js:491 templates/modals.html:76 msgid "Accept" msgstr "" -#: templates/js/modals.js:474 templates/modals.html:72 +#: templates/js/modals.js:492 templates/modals.html:75 msgid "Cancel" msgstr "" -#: templates/js/modals.js:538 +#: templates/js/modals.js:556 msgid "Loading Data" msgstr "" -#: templates/js/modals.js:549 templates/js/modals.js:808 -#: templates/modals.html:29 templates/modals.html:53 +#: templates/js/modals.js:567 templates/js/modals.js:845 +#: templates/modals.html:30 templates/modals.html:55 msgid "Submit" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Invalid response from server" msgstr "" -#: templates/js/modals.js:760 +#: templates/js/modals.js:797 msgid "Form data missing from server response" msgstr "" -#: templates/js/modals.js:773 +#: templates/js/modals.js:810 msgid "Error posting form data" msgstr "" -#: templates/js/modals.js:857 +#: templates/js/modals.js:901 msgid "JSON response missing form data" msgstr "" -#: templates/js/modals.js:867 +#: templates/js/modals.js:911 msgid "No Response" msgstr "" -#: templates/js/modals.js:868 +#: templates/js/modals.js:912 msgid "No response from the InvenTree server" msgstr "" -#: templates/js/modals.js:872 +#: templates/js/modals.js:916 msgid "Error 400: Bad Request" msgstr "" -#: templates/js/modals.js:873 +#: templates/js/modals.js:917 msgid "Server returned error code 400" msgstr "" -#: templates/js/modals.js:877 +#: templates/js/modals.js:921 msgid "Error 401: Not Authenticated" msgstr "" -#: templates/js/modals.js:878 +#: templates/js/modals.js:922 msgid "Authentication credentials not supplied" msgstr "" -#: templates/js/modals.js:882 +#: templates/js/modals.js:926 msgid "Error 403: Permission Denied" msgstr "" -#: templates/js/modals.js:883 +#: templates/js/modals.js:927 msgid "You do not have the required permissions to access this function" msgstr "" -#: templates/js/modals.js:887 +#: templates/js/modals.js:931 msgid "Error 404: Resource Not Found" msgstr "" -#: templates/js/modals.js:888 +#: templates/js/modals.js:932 msgid "The requested resource could not be located on the server" msgstr "" -#: templates/js/modals.js:892 +#: templates/js/modals.js:936 msgid "Error 408: Timeout" msgstr "" -#: templates/js/modals.js:893 +#: templates/js/modals.js:937 msgid "Connection timeout while requesting data from server" msgstr "" -#: templates/js/modals.js:896 +#: templates/js/modals.js:940 msgid "Error requesting form data" msgstr "" @@ -6542,7 +6716,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.js:409 templates/js/table_filters.js:318 +#: templates/js/part.js:409 templates/js/table_filters.js:319 msgid "Low stock" msgstr "" @@ -6740,7 +6914,7 @@ msgstr "" msgid "Stock item is destroyed" msgstr "" -#: templates/js/stock.js:620 templates/js/table_filters.js:138 +#: templates/js/stock.js:620 templates/js/table_filters.js:139 msgid "Depleted" msgstr "" @@ -6764,189 +6938,213 @@ msgstr "" msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:1050 +#: templates/js/stock.js:994 +msgid "Invalid date" +msgstr "" + +#: templates/js/stock.js:1036 +msgid "Location no longer exists" +msgstr "" + +#: templates/js/stock.js:1055 +msgid "Purchase order no longer exists" +msgstr "" + +#: templates/js/stock.js:1074 +msgid "Customer no longer exists" +msgstr "" + +#: templates/js/stock.js:1092 +msgid "Stock item no longer exists" +msgstr "" + +#: templates/js/stock.js:1115 +msgid "Added" +msgstr "" + +#: templates/js/stock.js:1123 +msgid "Removed" +msgstr "" + +#: templates/js/stock.js:1155 msgid "No user information" msgstr "" -#: templates/js/stock.js:1060 +#: templates/js/stock.js:1167 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1061 +#: templates/js/stock.js:1168 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1170 +#: templates/js/stock.js:1292 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1269 +#: templates/js/stock.js:1391 msgid "Serial" msgstr "" -#: templates/js/stock.js:1362 templates/js/table_filters.js:171 +#: templates/js/stock.js:1484 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1387 +#: templates/js/stock.js:1509 msgid "Install item" msgstr "" -#: templates/js/table_filters.js:42 +#: templates/js/table_filters.js:43 msgid "Trackable Part" msgstr "" -#: templates/js/table_filters.js:46 +#: templates/js/table_filters.js:47 msgid "Validated" msgstr "" -#: templates/js/table_filters.js:71 +#: templates/js/table_filters.js:72 msgid "Include locations" msgstr "" -#: templates/js/table_filters.js:81 templates/js/table_filters.js:82 -#: templates/js/table_filters.js:295 +#: templates/js/table_filters.js:82 templates/js/table_filters.js:83 +#: templates/js/table_filters.js:296 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.js:92 templates/js/table_filters.js:181 +#: templates/js/table_filters.js:93 templates/js/table_filters.js:182 msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.js:95 templates/js/table_filters.js:188 +#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.js:96 templates/js/table_filters.js:189 +#: templates/js/table_filters.js:97 templates/js/table_filters.js:190 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.js:99 templates/js/table_filters.js:192 +#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.js:100 templates/js/table_filters.js:193 +#: templates/js/table_filters.js:101 templates/js/table_filters.js:194 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.js:103 templates/js/table_filters.js:104 -#: templates/js/table_filters.js:184 templates/js/table_filters.js:185 +#: templates/js/table_filters.js:104 templates/js/table_filters.js:105 +#: templates/js/table_filters.js:185 templates/js/table_filters.js:186 msgid "Serial number" msgstr "" -#: templates/js/table_filters.js:108 templates/js/table_filters.js:202 +#: templates/js/table_filters.js:109 templates/js/table_filters.js:203 msgid "Batch code" msgstr "" -#: templates/js/table_filters.js:118 templates/js/table_filters.js:285 +#: templates/js/table_filters.js:119 templates/js/table_filters.js:286 msgid "Active parts" msgstr "" -#: templates/js/table_filters.js:119 +#: templates/js/table_filters.js:120 msgid "Show stock for active parts" msgstr "" -#: templates/js/table_filters.js:124 +#: templates/js/table_filters.js:125 msgid "Part is an assembly" msgstr "" -#: templates/js/table_filters.js:128 +#: templates/js/table_filters.js:129 msgid "Is allocated" msgstr "" -#: templates/js/table_filters.js:129 +#: templates/js/table_filters.js:130 msgid "Item has been allocated" msgstr "" -#: templates/js/table_filters.js:134 +#: templates/js/table_filters.js:135 msgid "Include stock in sublocations" msgstr "" -#: templates/js/table_filters.js:139 +#: templates/js/table_filters.js:140 msgid "Show stock items which are depleted" msgstr "" -#: templates/js/table_filters.js:146 +#: templates/js/table_filters.js:147 msgid "Show stock items which have expired" msgstr "" -#: templates/js/table_filters.js:151 +#: templates/js/table_filters.js:152 msgid "Show stock which is close to expiring" msgstr "" -#: templates/js/table_filters.js:157 +#: templates/js/table_filters.js:158 msgid "Show items which are in stock" msgstr "" -#: templates/js/table_filters.js:161 +#: templates/js/table_filters.js:162 msgid "In Production" msgstr "" -#: templates/js/table_filters.js:162 +#: templates/js/table_filters.js:163 msgid "Show items which are in production" msgstr "" -#: templates/js/table_filters.js:166 +#: templates/js/table_filters.js:167 msgid "Include Variants" msgstr "" -#: templates/js/table_filters.js:167 +#: templates/js/table_filters.js:168 msgid "Include stock items for variant parts" msgstr "" -#: templates/js/table_filters.js:172 +#: templates/js/table_filters.js:173 msgid "Show stock items which are installed in another item" msgstr "" -#: templates/js/table_filters.js:176 -msgid "Sent to customer" -msgstr "" - -#: templates/js/table_filters.js:177 +#: templates/js/table_filters.js:178 msgid "Show items which have been assigned to a customer" msgstr "" -#: templates/js/table_filters.js:197 templates/js/table_filters.js:198 +#: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" msgstr "" -#: templates/js/table_filters.js:231 +#: templates/js/table_filters.js:232 msgid "Build status" msgstr "" -#: templates/js/table_filters.js:250 templates/js/table_filters.js:267 +#: templates/js/table_filters.js:251 templates/js/table_filters.js:268 msgid "Order status" msgstr "" -#: templates/js/table_filters.js:255 templates/js/table_filters.js:272 +#: templates/js/table_filters.js:256 templates/js/table_filters.js:273 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.js:296 +#: templates/js/table_filters.js:297 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.js:300 +#: templates/js/table_filters.js:301 msgid "Has IPN" msgstr "" -#: templates/js/table_filters.js:301 +#: templates/js/table_filters.js:302 msgid "Part has internal part number" msgstr "" -#: templates/js/table_filters.js:306 +#: templates/js/table_filters.js:307 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.js:314 +#: templates/js/table_filters.js:315 msgid "Stock available" msgstr "" -#: templates/js/table_filters.js:330 +#: templates/js/table_filters.js:331 msgid "Starred" msgstr "" -#: templates/js/table_filters.js:342 +#: templates/js/table_filters.js:343 msgid "Purchasable" msgstr "" @@ -7003,7 +7201,7 @@ msgstr "" msgid "All" msgstr "" -#: templates/modals.html:21 templates/modals.html:46 +#: templates/modals.html:21 templates/modals.html:47 msgid "Form errors exist" msgstr "" @@ -7115,31 +7313,47 @@ msgstr "" msgid "Instance Name" msgstr "" -#: templates/stats.html:19 -msgid "Server status" +#: templates/stats.html:18 +msgid "Database" msgstr "" -#: templates/stats.html:22 -msgid "Healthy" +#: templates/stats.html:26 +msgid "Server is running in debug mode" msgstr "" -#: templates/stats.html:24 -msgid "Issues detected" -msgstr "" - -#: templates/stats.html:31 -msgid "Background Worker" +#: templates/stats.html:33 +msgid "Docker Mode" msgstr "" #: templates/stats.html:34 -msgid "Background worker not running" +msgid "Server is deployed using docker" msgstr "" -#: templates/stats.html:42 -msgid "Email Settings" +#: templates/stats.html:40 +msgid "Server status" +msgstr "" + +#: templates/stats.html:43 +msgid "Healthy" msgstr "" #: templates/stats.html:45 +msgid "Issues detected" +msgstr "" + +#: templates/stats.html:52 +msgid "Background Worker" +msgstr "" + +#: templates/stats.html:55 +msgid "Background worker not running" +msgstr "" + +#: templates/stats.html:63 +msgid "Email Settings" +msgstr "" + +#: templates/stats.html:66 msgid "Email settings not configured" msgstr "" @@ -7258,3 +7472,4 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" + diff --git a/crowdin.yml b/crowdin.yml index 0fa92db24d..ad69a576eb 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,6 @@ +"commit_message": "Fix: New translations %original_file_name% from Crowdin" +"append_commit_message": false + files: - source: /InvenTree/locale/en/LC_MESSAGES/django.po translation: /InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name% From 01d444279c35b3ee6c7f04c7f250d5f360105e97 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 22:11:24 +1000 Subject: [PATCH 199/300] Add setting for fixer.io API key --- InvenTree/common/models.py | 6 ++++++ InvenTree/templates/InvenTree/settings/global.html | 1 + 2 files changed, 7 insertions(+) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 99712b2a93..e499e9b801 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -87,6 +87,12 @@ class InvenTreeSetting(models.Model): 'choices': djmoney.settings.CURRENCY_CHOICES, }, + 'INVENTREE_FIXER_API_KEY': { + 'name': _('fixer.io API key'), + 'description': _('API key for fixer.io currency conversion service'), + 'default': '', + }, + 'INVENTREE_DOWNLOAD_FROM_URL': { 'name': _('Download from URL'), 'description': _('Allow download of remote images and files from external URL'), diff --git a/InvenTree/templates/InvenTree/settings/global.html b/InvenTree/templates/InvenTree/settings/global.html index a0347490d0..5c5dccfb2a 100644 --- a/InvenTree/templates/InvenTree/settings/global.html +++ b/InvenTree/templates/InvenTree/settings/global.html @@ -20,6 +20,7 @@ {% include "InvenTree/settings/setting.html" with key="INVENTREE_BASE_URL" icon="fa-globe" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_COMPANY_NAME" icon="fa-building" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} + {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DOWNLOAD_FROM_URL" icon="fa-cloud-download-alt" %}
    From 663f5562e8e7bc83f5d8db3caa6e7acb6d2632bb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 22:41:26 +1000 Subject: [PATCH 200/300] Schedule a daily task to update currency information --- InvenTree/InvenTree/apps.py | 5 +++++ InvenTree/InvenTree/settings.py | 3 ++- InvenTree/InvenTree/tasks.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index 148638b5b2..aa60058dcf 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -44,3 +44,8 @@ class InvenTreeConfig(AppConfig): schedule_type=Schedule.MINUTES, minutes=15 ) + + InvenTree.tasks.schedule_task( + 'InvenTree.tasks.update_exchange_rates', + schedule_type=Schedule.DAILY, + ) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 67a500a07a..5cf0b0c544 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -513,7 +513,8 @@ CURRENCIES = CONFIG.get( ], ) -# TODO - Allow live web-based backends in the future +BASE_CURRENCY = CONFIG.get('base_currency', 'USD') + EXCHANGE_BACKEND = 'InvenTree.exchange.InvenTreeManualExchangeBackend' # Extract email settings from the config file diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 6c01e03aa6..8640395d42 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -161,6 +161,34 @@ def check_for_updates(): ) +def update_exchange_rates(): + """ + If an API key for fixer.io has been provided, attempt to update currency exchange rates + """ + + try: + import common.models + from django.conf import settings + from djmoney.contrib.exchange.backends import FixerBackend + except AppRegistryNotReady: + # Apps not yet loaded! + return + + fixer_api_key = common.models.InvenTreeSetting.get_setting('INVENTREE_FIXER_API_KEY', '').strip() + + if not fixer_api_key: + # API key not provided + return + + backend = FixerBackend(access_key=fixer_api_key) + + currencies = ','.join(settings.CURRENCIES) + + base = settings.BASE_CURRENCY + + result = backend.update_rates(base_currency=base, symbols=currencies) + + def send_email(subject, body, recipients, from_email=None): """ Send an email with the specified subject and body, From 4101e2568011b518cc29d0000d3674fc8a01d52e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 18 May 2021 22:41:57 +1000 Subject: [PATCH 201/300] Style fixes --- InvenTree/InvenTree/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 8640395d42..b81b4e6de4 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -186,7 +186,7 @@ def update_exchange_rates(): base = settings.BASE_CURRENCY - result = backend.update_rates(base_currency=base, symbols=currencies) + backend.update_rates(base_currency=base, symbols=currencies) def send_email(subject, body, recipients, from_email=None): From 34ded08ee717a961d5d7eaf70590f415416ca4a6 Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 19 May 2021 16:17:03 -0400 Subject: [PATCH 202/300] Added InvenTreeFixerExchangeBackend class --- InvenTree/InvenTree/exchange.py | 44 +++++++++++++++++++++++++++++++++ InvenTree/InvenTree/settings.py | 2 +- InvenTree/InvenTree/tasks.py | 26 ++++++++----------- InvenTree/config_template.yaml | 7 ++++++ 4 files changed, 62 insertions(+), 17 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 06de4861ec..59d2883e2a 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,4 +1,10 @@ +from django.conf import settings as inventree_settings + +from djmoney import settings as djmoney_settings from djmoney.contrib.exchange.backends.base import BaseExchangeBackend +from djmoney.contrib.exchange.backends import FixerBackend + +from common.models import InvenTreeSetting class InvenTreeManualExchangeBackend(BaseExchangeBackend): @@ -19,3 +25,41 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): """ return {} + + +class InvenTreeFixerExchangeBackend(FixerBackend): + """ + Backend for updating currency exchange rates using Fixer.IO API + """ + + def get_api_key(self): + """ Get API key from global settings """ + + fixer_api_key = InvenTreeSetting.get_setting('INVENTREE_FIXER_API_KEY', '').strip() + + if not fixer_api_key: + # API key not provided + return None + + return fixer_api_key + + def __init__(self): + """ Override FixerBackend init to get access_key from global settings """ + + fixer_api_key = self.get_api_key() + + super().__init__(url=djmoney_settings.FIXER_URL, access_key=fixer_api_key) + + def update_rates(self): + """ Override update_rates method using currencies found in the settings """ + + currencies = ','.join(inventree_settings.CURRENCIES) + + base = inventree_settings.BASE_CURRENCY + + super().update_rates(base_currency=base, symbols=currencies) + + def get_rates(self, **kwargs): + """ Returns a mapping : """ + + return {} diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 5cf0b0c544..e99c3a3eea 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -515,7 +515,7 @@ CURRENCIES = CONFIG.get( BASE_CURRENCY = CONFIG.get('base_currency', 'USD') -EXCHANGE_BACKEND = 'InvenTree.exchange.InvenTreeManualExchangeBackend' +EXCHANGE_BACKEND = 'InvenTree.exchange.' + CONFIG.get('exchange_backend', 'InvenTreeManualExchangeBackend') # Extract email settings from the config file email_config = CONFIG.get('email', {}) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index b81b4e6de4..0076bb9544 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -163,30 +163,24 @@ def check_for_updates(): def update_exchange_rates(): """ - If an API key for fixer.io has been provided, attempt to update currency exchange rates + Update backend rates """ try: - import common.models + from .exchange import InvenTreeManualExchangeBackend, InvenTreeFixerExchangeBackend from django.conf import settings - from djmoney.contrib.exchange.backends import FixerBackend except AppRegistryNotReady: # Apps not yet loaded! return + + # Get backend + if 'InvenTreeManualExchangeBackend' in settings.EXCHANGE_BACKEND: + backend = InvenTreeFixerExchangeBackend() + else: + backend = InvenTreeManualExchangeBackend() - fixer_api_key = common.models.InvenTreeSetting.get_setting('INVENTREE_FIXER_API_KEY', '').strip() - - if not fixer_api_key: - # API key not provided - return - - backend = FixerBackend(access_key=fixer_api_key) - - currencies = ','.join(settings.CURRENCIES) - - base = settings.BASE_CURRENCY - - backend.update_rates(base_currency=base, symbols=currencies) + # Update rates + backend.update_rates() def send_email(subject, body, recipients, from_email=None): diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 87dfb6b545..63525b0d79 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -62,6 +62,13 @@ currencies: - JPY - NZD - USD +# Define base currency (can also be defined in the global settings) +# base_currency: USD +# Define exchange backend +# Choices are: +# - InvenTreeManualExchangeBackend +# - InvenTreeFixerExchangeBackend +exchange_backend: InvenTreeFixerExchangeBackend # Email backend configuration # Ref: https://docs.djangoproject.com/en/dev/topics/email/ From 6d5b2d3227f1bf0a92971e473ab226374e8359a3 Mon Sep 17 00:00:00 2001 From: eeintech Date: Wed, 19 May 2021 17:06:41 -0400 Subject: [PATCH 203/300] Added 'Currencies' settings view in global settings --- InvenTree/InvenTree/tasks.py | 4 +- InvenTree/InvenTree/urls.py | 3 ++ InvenTree/InvenTree/views.py | 15 +++++++ .../InvenTree/settings/currencies.html | 43 +++++++++++++++++++ .../templates/InvenTree/settings/global.html | 2 - .../templates/InvenTree/settings/tabs.html | 3 ++ 6 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 InvenTree/templates/InvenTree/settings/currencies.html diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 0076bb9544..fb6a45f368 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -175,9 +175,9 @@ def update_exchange_rates(): # Get backend if 'InvenTreeManualExchangeBackend' in settings.EXCHANGE_BACKEND: - backend = InvenTreeFixerExchangeBackend() - else: backend = InvenTreeManualExchangeBackend() + else: + backend = InvenTreeFixerExchangeBackend() # Update rates backend.update_rates() diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index ab2ced7d5e..d3132ca2a8 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -41,6 +41,7 @@ from .views import IndexView, SearchView, DatabaseStatsView from .views import SettingsView, EditUserView, SetPasswordView from .views import AppearanceSelectView, SettingCategorySelectView from .views import DynamicJsView +from .views import ExchangeRatesView from common.views import SettingEdit @@ -90,6 +91,8 @@ settings_urls = [ url(r'^build/?', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'), url(r'^purchase-order/?', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'), url(r'^sales-order/?', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'), + url(r'^currencies/?', SettingsView.as_view(template_name='InvenTree/settings/currencies.html'), name='settings-currencies'), + url(r'^echange-rates/?', ExchangeRatesView.as_view(), name='refresh-exchange-rates'), url(r'^(?P\d+)/edit/', SettingEdit.as_view(), name='setting-edit'), diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index d285efae36..bd03a18dda 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -27,6 +27,7 @@ from users.models import check_user_role, RuleSet from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import ColorThemeSelectForm, SettingCategorySelectForm from .helpers import str2bool +from .tasks import update_exchange_rates from rest_framework import views @@ -908,3 +909,17 @@ class DatabaseStatsView(AjaxView): """ return ctx + + +class ExchangeRatesView(SettingsView): + + success_url = reverse_lazy('settings-currencies') + + def post(self, request, *args, **kwargs): + + # Process exchange rates + update_exchange_rates() + + # TODO: Update context + + return HttpResponseRedirect(self.success_url) diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html new file mode 100644 index 0000000000..9ec5b518fb --- /dev/null +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -0,0 +1,43 @@ +{% extends "InvenTree/settings/settings.html" %} +{% load i18n %} +{% load inventree_extras %} + +{% block tabs %} +{% include "InvenTree/settings/tabs.html" with tab='currencies' %} +{% endblock %} + +{% block subtitle %} +{% trans "Currency Settings" %} +{% endblock %} + +{% block settings %} + + + {% include "InvenTree/settings/header.html" %} + + {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} + {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} + +
    + +
    +
    +

    {% trans "Exchange Rates" %}

    +
    +
    + + +
    + +
    + {% csrf_token %} + +
    + +{% endblock %} + +{% block js_ready %} +{{ block.super }} +{% comment %} TODO: Update exchange-rates table! {% endcomment %} +{% comment %} Or do it using context instead of JS? {% endcomment %} +{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/settings/global.html b/InvenTree/templates/InvenTree/settings/global.html index 5c5dccfb2a..fd91dafc67 100644 --- a/InvenTree/templates/InvenTree/settings/global.html +++ b/InvenTree/templates/InvenTree/settings/global.html @@ -19,8 +19,6 @@ {% include "InvenTree/settings/setting.html" with key="INVENTREE_INSTANCE_TITLE" icon="fa-info-circle" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_BASE_URL" icon="fa-globe" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_COMPANY_NAME" icon="fa-building" %} - {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} - {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DOWNLOAD_FROM_URL" icon="fa-cloud-download-alt" %} diff --git a/InvenTree/templates/InvenTree/settings/tabs.html b/InvenTree/templates/InvenTree/settings/tabs.html index 3f8be0a313..360618fc34 100644 --- a/InvenTree/templates/InvenTree/settings/tabs.html +++ b/InvenTree/templates/InvenTree/settings/tabs.html @@ -36,5 +36,8 @@
  • {% trans "Sales Orders" %}
  • +
  • + {% trans "Currencies" %} +
  • {% endif %} From bed6a7e49c11f2cbb8ad4eb12ef1e6a16f16e616 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 20 May 2021 09:49:56 -0400 Subject: [PATCH 204/300] Added exchange rates form --- InvenTree/InvenTree/exchange.py | 61 +++++++++++++------ InvenTree/InvenTree/forms.py | 36 ++++++++++- InvenTree/InvenTree/tasks.py | 10 +-- InvenTree/InvenTree/urls.py | 5 +- InvenTree/InvenTree/views.py | 37 ++++++++++- .../InvenTree/settings/currencies.html | 19 +++--- 6 files changed, 125 insertions(+), 43 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 59d2883e2a..03891828a0 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,12 +1,21 @@ +from django.core.exceptions import ImproperlyConfigured from django.conf import settings as inventree_settings from djmoney import settings as djmoney_settings from djmoney.contrib.exchange.backends.base import BaseExchangeBackend -from djmoney.contrib.exchange.backends import FixerBackend from common.models import InvenTreeSetting +def get_exchange_rate_backend(): + """ Return the exchange rate backend set by user """ + + if 'InvenTreeManualExchangeBackend' in inventree_settings.EXCHANGE_BACKEND: + return InvenTreeManualExchangeBackend() + else: + return InvenTreeFixerExchangeBackend() + + class InvenTreeManualExchangeBackend(BaseExchangeBackend): """ Backend for manually updating currency exchange rates @@ -16,22 +25,39 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): Specifically: https://github.com/django-money/django-money/tree/master/djmoney/contrib/exchange/backends """ - name = "inventree" + name = 'inventree' url = None + default_currency = None + currencies = [] + + def update_default_currency(self): + + self.default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', inventree_settings.BASE_CURRENCY) + + def __init__(self, url=None): + + self.url = url + + self.update_default_currency() + + self.currencies = inventree_settings.CURRENCIES + + super().__init__() def get_rates(self, **kwargs): - """ - Do not get any rates... - """ + """ Returns a mapping : """ return {} -class InvenTreeFixerExchangeBackend(FixerBackend): +class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): """ Backend for updating currency exchange rates using Fixer.IO API """ + name = 'fixer.io' + access_key = None + def get_api_key(self): """ Get API key from global settings """ @@ -48,18 +74,17 @@ class InvenTreeFixerExchangeBackend(FixerBackend): fixer_api_key = self.get_api_key() - super().__init__(url=djmoney_settings.FIXER_URL, access_key=fixer_api_key) + if fixer_api_key is None: + raise ImproperlyConfigured("fixer.io API key is needed to use InvenTreeFixerExchangeBackend") + + self.access_key = fixer_api_key + + super().__init__(url=djmoney_settings.FIXER_URL) def update_rates(self): - """ Override update_rates method using currencies found in the settings """ + """ Override update_rates method using currencies found in the settings + """ + + symbols = ','.join(self.currencies) - currencies = ','.join(inventree_settings.CURRENCIES) - - base = inventree_settings.BASE_CURRENCY - - super().update_rates(base_currency=base, symbols=currencies) - - def get_rates(self, **kwargs): - """ Returns a mapping : """ - - return {} + super().update_rates(base_currency=self.base_currency, symbols=symbols) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 52d1c8758f..a744671afb 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -7,12 +7,15 @@ from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ from django import forms +from django.contrib.auth.models import User + from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Field from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div -from django.contrib.auth.models import User + from common.models import ColorTheme from part.models import PartCategory +from .exchange import InvenTreeManualExchangeBackend class HelperForm(forms.ModelForm): @@ -236,3 +239,34 @@ class SettingCategorySelectForm(forms.ModelForm): css_class='row', ), ) + + +class SettingExchangeRatesForm(forms.Form): + """ Form for displaying and setting currency exchange rates manually """ + + def __init__(self, *args, **kwargs): + + super().__init__(*args, **kwargs) + + exchange_rate_backend = InvenTreeManualExchangeBackend() + + # Update default currency (in case it has changed) + exchange_rate_backend.update_default_currency() + + for currency in exchange_rate_backend.currencies: + if currency != exchange_rate_backend.default_currency: + # Set field name + field_name = currency + # Set field input box + self.fields[field_name] = forms.CharField( + label=field_name, + required=False, + widget=forms.NumberInput(attrs={ + 'name': field_name, + 'class': 'numberinput', + 'type': 'number', + 'min': '0', + 'step': 'any', + 'value': '', + }) + ) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index fb6a45f368..0468365dae 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -167,17 +167,13 @@ def update_exchange_rates(): """ try: - from .exchange import InvenTreeManualExchangeBackend, InvenTreeFixerExchangeBackend - from django.conf import settings + from .exchange import get_exchange_rate_backend except AppRegistryNotReady: # Apps not yet loaded! return - # Get backend - if 'InvenTreeManualExchangeBackend' in settings.EXCHANGE_BACKEND: - backend = InvenTreeManualExchangeBackend() - else: - backend = InvenTreeFixerExchangeBackend() + # Get exchange rate backend + backend = get_exchange_rate_backend() # Update rates backend.update_rates() diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index d3132ca2a8..d297dc18ad 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -41,7 +41,7 @@ from .views import IndexView, SearchView, DatabaseStatsView from .views import SettingsView, EditUserView, SetPasswordView from .views import AppearanceSelectView, SettingCategorySelectView from .views import DynamicJsView -from .views import ExchangeRatesView +from .views import CurrencySettingsView from common.views import SettingEdit @@ -91,8 +91,7 @@ settings_urls = [ url(r'^build/?', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'), url(r'^purchase-order/?', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'), url(r'^sales-order/?', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'), - url(r'^currencies/?', SettingsView.as_view(template_name='InvenTree/settings/currencies.html'), name='settings-currencies'), - url(r'^echange-rates/?', ExchangeRatesView.as_view(), name='refresh-exchange-rates'), + url(r'^currencies/?', CurrencySettingsView.as_view(), name='settings-currencies'), url(r'^(?P\d+)/edit/', SettingEdit.as_view(), name='setting-edit'), diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index bd03a18dda..50f4a095e8 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -26,8 +26,9 @@ from users.models import check_user_role, RuleSet from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import ColorThemeSelectForm, SettingCategorySelectForm +from .forms import SettingExchangeRatesForm from .helpers import str2bool -from .tasks import update_exchange_rates +from .exchange import get_exchange_rate_backend from rest_framework import views @@ -911,14 +912,44 @@ class DatabaseStatsView(AjaxView): return ctx -class ExchangeRatesView(SettingsView): +class CurrencySettingsView(FormView): + form_class = SettingExchangeRatesForm + template_name = 'InvenTree/settings/currencies.html' success_url = reverse_lazy('settings-currencies') + def get_context_data(self, **kwargs): + + context = super().get_context_data(**kwargs) + + # Get exchange rate backend + exchange_rate_backend = get_exchange_rate_backend() + + context['exchange_backend'] = exchange_rate_backend.name + + return context + + def get_form(self): + + form = super().get_form() + + # Get exchange rate backend + exchange_rate_backend = get_exchange_rate_backend() + + if exchange_rate_backend.name == 'fixer.io': + # Disable all the fields + for field in form.fields: + form.fields[field].disabled = True + + return form + def post(self, request, *args, **kwargs): + # Get exchange rate backend + exchange_rate_backend = get_exchange_rate_backend() + # Process exchange rates - update_exchange_rates() + exchange_rate_backend.update_rates() # TODO: Update context diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index 9ec5b518fb..52d6558bad 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -26,18 +26,15 @@
    - -
    - -
    + {% csrf_token %} - + {% load crispy_forms_tags %} + {% crispy form %} + {% if exchange_backend == 'fixer.io' %} + + {% else %} + + {% endif %}
    {% endblock %} - -{% block js_ready %} -{{ block.super }} -{% comment %} TODO: Update exchange-rates table! {% endcomment %} -{% comment %} Or do it using context instead of JS? {% endcomment %} -{% endblock %} \ No newline at end of file From 747b0554e1f92323a3da20e82a3415cafc74a639 Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 20 May 2021 13:45:26 -0400 Subject: [PATCH 205/300] Ready for review --- InvenTree/InvenTree/exchange.py | 75 +++++++++++++++---- InvenTree/InvenTree/forms.py | 6 +- InvenTree/InvenTree/helpers.py | 18 ++++- InvenTree/InvenTree/views.py | 61 ++++++++++++--- InvenTree/common/forms.py | 22 +----- .../InvenTree/settings/currencies.html | 14 +++- 6 files changed, 148 insertions(+), 48 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 03891828a0..ce1db06711 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -3,6 +3,7 @@ from django.conf import settings as inventree_settings from djmoney import settings as djmoney_settings from djmoney.contrib.exchange.backends.base import BaseExchangeBackend +from djmoney.contrib.exchange.models import Rate from common.models import InvenTreeSetting @@ -27,19 +28,24 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): name = 'inventree' url = None - default_currency = None + base_currency = None currencies = [] def update_default_currency(self): + """ Update to base currency """ - self.default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', inventree_settings.BASE_CURRENCY) + self.base_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', inventree_settings.BASE_CURRENCY) def __init__(self, url=None): + """ Overrides init to update url, base currency and currencies """ self.url = url self.update_default_currency() + # Update name + self.name = self.name + '-' + self.base_currency.lower() + self.currencies = inventree_settings.CURRENCIES super().__init__() @@ -47,7 +53,22 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): def get_rates(self, **kwargs): """ Returns a mapping : """ - return {} + return kwargs.get('rates', {}) + + def get_stored_rates(self): + """ Returns stored rate for specified backend and base currency """ + + stored_rates = {} + + stored_rates_obj = Rate.objects.all().prefetch_related('backend') + + for rate in stored_rates_obj: + # Find match for backend and base currency + if rate.backend.name == self.name and rate.backend.base_currency == self.base_currency: + # print(f'{rate.currency} | {rate.value} | {rate.backend} | {rate.backend.base_currency}') + stored_rates[rate.currency] = rate.value + + return stored_rates class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): @@ -55,7 +76,7 @@ class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): Backend for updating currency exchange rates using Fixer.IO API """ - name = 'fixer.io' + name = 'fixer' access_key = None def get_api_key(self): @@ -67,24 +88,48 @@ class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): # API key not provided return None - return fixer_api_key - - def __init__(self): - """ Override FixerBackend init to get access_key from global settings """ - - fixer_api_key = self.get_api_key() - - if fixer_api_key is None: - raise ImproperlyConfigured("fixer.io API key is needed to use InvenTreeFixerExchangeBackend") - self.access_key = fixer_api_key + def __init__(self): + """ Override init to get access_key from global settings """ + + self.get_api_key() + + if self.access_key is None: + raise ImproperlyConfigured("fixer.io API key is needed to use InvenTreeFixerExchangeBackend") + super().__init__(url=djmoney_settings.FIXER_URL) - def update_rates(self): + def get_params(self): + """ Returns parameters (access key) """ + + return {"access_key": self.access_key} + + def update_rates(self, base_currency=None): """ Override update_rates method using currencies found in the settings """ + + if base_currency: + self.base_currency = base_currency + else: + self.update_default_currency() symbols = ','.join(self.currencies) super().update_rates(base_currency=self.base_currency, symbols=symbols) + + def get_rates(self, **params): + """ Returns a mapping : """ + + # Set base currency + params.update(base=self.base_currency) + + response = self.get_response(**params) + + try: + return self.parse_json(response)['rates'] + except KeyError: + # API response did not contain any rate + pass + + return {} diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index a744671afb..488e982ddc 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -15,6 +15,7 @@ from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppende from common.models import ColorTheme from part.models import PartCategory + from .exchange import InvenTreeManualExchangeBackend @@ -254,7 +255,7 @@ class SettingExchangeRatesForm(forms.Form): exchange_rate_backend.update_default_currency() for currency in exchange_rate_backend.currencies: - if currency != exchange_rate_backend.default_currency: + if currency != exchange_rate_backend.base_currency: # Set field name field_name = currency # Set field input box @@ -264,9 +265,10 @@ class SettingExchangeRatesForm(forms.Form): widget=forms.NumberInput(attrs={ 'name': field_name, 'class': 'numberinput', + 'style': 'width: 200px;', 'type': 'number', 'min': '0', 'step': 'any', - 'value': '', + 'value': 0, }) ) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 1097c5663b..9d00697230 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -8,7 +8,7 @@ import json import os.path from PIL import Image -from decimal import Decimal +from decimal import Decimal, InvalidOperation from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse @@ -606,3 +606,19 @@ def getNewestMigrationFile(app, exclude_extension=True): newest_file = newest_file.replace('.py', '') return newest_file + + +def clean_decimal(number): + """ Clean-up decimal value """ + + # Check if empty + if number is None or number == '': + return Decimal(0) + + # Check if decimal type + try: + clean_number = Decimal(number) + except InvalidOperation: + clean_number = number + + return clean_number.quantize(Decimal(1)) if clean_number == clean_number.to_integral() else clean_number.normalize() diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 50f4a095e8..48e42dd890 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -23,6 +23,7 @@ from part.models import Part, PartCategory from stock.models import StockLocation, StockItem from common.models import InvenTreeSetting, ColorTheme from users.models import check_user_role, RuleSet +from InvenTree.helpers import clean_decimal from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import ColorThemeSelectForm, SettingCategorySelectForm @@ -918,12 +919,30 @@ class CurrencySettingsView(FormView): template_name = 'InvenTree/settings/currencies.html' success_url = reverse_lazy('settings-currencies') + exchange_rate_backend = None + + def get_exchange_rate_backend(self): + + if not self.exchange_rate_backend: + self.exchange_rate_backend = get_exchange_rate_backend() + + return self.exchange_rate_backend + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + # Set default API result + if 'api_rates_success' not in context: + context['default_currency'] = True + else: + # Update form + context['form'] = self.get_form() + # Get exchange rate backend - exchange_rate_backend = get_exchange_rate_backend() + exchange_rate_backend = self.get_exchange_rate_backend() + + context['default_currency'] = exchange_rate_backend.base_currency context['exchange_backend'] = exchange_rate_backend.name @@ -934,23 +953,45 @@ class CurrencySettingsView(FormView): form = super().get_form() # Get exchange rate backend - exchange_rate_backend = get_exchange_rate_backend() + exchange_rate_backend = self.get_exchange_rate_backend() - if exchange_rate_backend.name == 'fixer.io': - # Disable all the fields - for field in form.fields: + # Get stored exchange rates + stored_rates = exchange_rate_backend.get_stored_rates() + + for field in form.fields: + if 'fixer' in exchange_rate_backend.name: + # Disable all the fields form.fields[field].disabled = True + form.fields[field].initial = clean_decimal(stored_rates.get(field, 0)) return form def post(self, request, *args, **kwargs): + form = self.get_form() + # Get exchange rate backend - exchange_rate_backend = get_exchange_rate_backend() + exchange_rate_backend = self.get_exchange_rate_backend() - # Process exchange rates - exchange_rate_backend.update_rates() + if 'fixer' in exchange_rate_backend.name: + # Refresh rate from Fixer.IO API + exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency) + # Check if rates have been updated + if not exchange_rate_backend.get_stored_rates(): + # Update context + context = {'api_rates_success': False} + # Return view with updated context + return self.render_to_response(self.get_context_data(form=form, **context)) + else: + # Update rates from form + manual_rates = {} - # TODO: Update context + if form.is_valid(): + for field, value in form.cleaned_data.items(): + manual_rates[field] = clean_decimal(value) - return HttpResponseRedirect(self.success_url) + exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency, **{'rates': manual_rates}) + else: + return self.form_invalid(form) + + return self.form_valid(form) diff --git a/InvenTree/common/forms.py b/InvenTree/common/forms.py index 8a0017e38b..bab7ede74c 100644 --- a/InvenTree/common/forms.py +++ b/InvenTree/common/forms.py @@ -5,14 +5,13 @@ Django forms for interacting with common objects # -*- coding: utf-8 -*- from __future__ import unicode_literals -from decimal import Decimal, InvalidOperation - from django import forms from django.utils.translation import gettext as _ from djmoney.forms.fields import MoneyField from InvenTree.forms import HelperForm +from InvenTree.helpers import clean_decimal from .files import FileManager from .models import InvenTreeSetting @@ -119,21 +118,6 @@ class MatchItem(forms.Form): super().__init__(*args, **kwargs) - def clean(number): - """ Clean-up decimal value """ - - # Check if empty - if not number: - return number - - # Check if decimal type - try: - clean_number = Decimal(number) - except InvalidOperation: - clean_number = number - - return clean_number.quantize(Decimal(1)) if clean_number == clean_number.to_integral() else clean_number.normalize() - # Setup FileManager file_manager.setup() @@ -160,7 +144,7 @@ class MatchItem(forms.Form): 'type': 'number', 'min': '0', 'step': 'any', - 'value': clean(row.get('quantity', '')), + 'value': clean_decimal(row.get('quantity', '')), }) ) @@ -202,7 +186,7 @@ class MatchItem(forms.Form): decimal_places=5, max_digits=19, required=False, - default_amount=clean(value), + default_amount=clean_decimal(value), ) else: self.fields[field_name] = forms.CharField( diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index 52d6558bad..10b5709238 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -22,11 +22,12 @@
    -

    {% trans "Exchange Rates" %}

    +

    {% trans "Exchange Rates - Convert to " %}{{ default_currency }}

    +
    {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} @@ -35,6 +36,17 @@ {% else %} {% endif %} +
    {% endblock %} + +{% block js_ready %} +{{ block.super }} + +{% if api_rates_success is False %} + var alert_msg = {% blocktrans %}"Failed to refresh exchange rates. Verify your API key and/or subscription plan" {% endblocktrans %}; + showAlertOrCache("alert-danger", alert_msg, null, 5000); +{% endif %} + +{% endblock %} \ No newline at end of file From 27799b43b236525b818fa32d2d4c66b57e0fa96b Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 20 May 2021 13:51:54 -0400 Subject: [PATCH 206/300] Template fix/improvement --- InvenTree/templates/InvenTree/settings/currencies.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index 10b5709238..fa9d234988 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -16,7 +16,9 @@ {% include "InvenTree/settings/header.html" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} + {% if 'fixer' in exchange_backend %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} + {% endif %} @@ -31,7 +33,7 @@ {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} - {% if exchange_backend == 'fixer.io' %} + {% if 'fixer' in exchange_backend %} {% else %} From bbd95f2c7059255b6217d01ea0c338b96deb8eae Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 20 May 2021 14:52:56 -0400 Subject: [PATCH 207/300] Fixed exchange rate backend test --- InvenTree/InvenTree/tasks.py | 2 +- InvenTree/company/tests.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 0468365dae..b3649bcdcf 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -176,7 +176,7 @@ def update_exchange_rates(): backend = get_exchange_rate_backend() # Update rates - backend.update_rates() + backend.update_rates(base_currency=backend.base_currency) def send_email(subject, body, recipients, from_email=None): diff --git a/InvenTree/company/tests.py b/InvenTree/company/tests.py index 5dd3bf81ab..e07516e180 100644 --- a/InvenTree/company/tests.py +++ b/InvenTree/company/tests.py @@ -11,7 +11,7 @@ from .models import Company, Contact, ManufacturerPart, SupplierPart from .models import rename_company_image from part.models import Part -from InvenTree.exchange import InvenTreeManualExchangeBackend +from InvenTree.exchange import get_exchange_rate_backend from djmoney.contrib.exchange.models import Rate @@ -40,13 +40,15 @@ class CompanySimpleTest(TestCase): self.acme0002 = SupplierPart.objects.get(SKU='ACME0002') self.zerglphs = SupplierPart.objects.get(SKU='ZERGLPHS') self.zergm312 = SupplierPart.objects.get(SKU='ZERGM312') - - InvenTreeManualExchangeBackend().update_rates() + + # Exchange rate backend + backend = get_exchange_rate_backend() + backend.update_rates(base_currency=backend.base_currency) Rate.objects.create( currency='AUD', value='1.35', - backend_id='inventree', + backend_id=backend.name, ) def test_company_model(self): From be3f37f28f286fcf05ef6b24af6526a6835331ed Mon Sep 17 00:00:00 2001 From: eeintech Date: Thu, 20 May 2021 15:22:18 -0400 Subject: [PATCH 208/300] Updated default currency backend --- InvenTree/config_template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 63525b0d79..7d301934f0 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -68,7 +68,7 @@ currencies: # Choices are: # - InvenTreeManualExchangeBackend # - InvenTreeFixerExchangeBackend -exchange_backend: InvenTreeFixerExchangeBackend +exchange_backend: InvenTreeManualExchangeBackend # Email backend configuration # Ref: https://docs.djangoproject.com/en/dev/topics/email/ From 240ff59b3010afe17370ac450aa1be757574a360 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 22 May 2021 20:56:56 +1000 Subject: [PATCH 209/300] Bump API version to 3 - New stock item history tracking is incompatible - Adds API info to the "about" dialog --- InvenTree/InvenTree/version.py | 11 +++++++++-- InvenTree/part/templatetags/inventree_extras.py | 6 ++++++ InvenTree/templates/about.html | 5 +++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 361fec152a..67962c7859 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -10,8 +10,15 @@ import common.models INVENTREE_SW_VERSION = "0.2.2 pre" -# Increment this number whenever there is a significant change to the API that any clients need to know about -INVENTREE_API_VERSION = 2 +""" +Increment thi API version number whenever there is a significant change to the API that any clients need to know about + +v3 -> 2021-05-22: + - The updated StockItem "history tracking" now uses a different interface + +""" + +INVENTREE_API_VERSION = 3 def inventreeInstanceName(): diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 734b365447..ceb2d11e31 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -119,6 +119,12 @@ def inventree_version(*args, **kwargs): return version.inventreeVersion() +@register.simple_tag() +def inventree_api_version(*args, **kwargs): + """ Return InvenTree API version """ + return version.inventreeApiVersion() + + @register.simple_tag() def django_version(*args, **kwargs): """ Return Django version string """ diff --git a/InvenTree/templates/about.html b/InvenTree/templates/about.html index f190ab2755..7b023295d1 100644 --- a/InvenTree/templates/about.html +++ b/InvenTree/templates/about.html @@ -29,6 +29,11 @@ {% endif %} + + + {% trans "API Version" %} + {% inventree_api_version %}{% include "clip.html" %} + {% trans "Django Version" %} From 53ce848145c3137581ce0b8ea7b6315e82165b74 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 22 May 2021 14:48:56 +0200 Subject: [PATCH 210/300] better translation --- InvenTree/templates/InvenTree/settings/currencies.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index fa9d234988..d9b046b9f5 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -24,7 +24,7 @@
    -

    {% trans "Exchange Rates - Convert to " %}{{ default_currency }}

    +

    {% blocktrans with cur=default_currency %}Exchange Rates - Convert to {{cur}}{% endblocktrans %}

    From 4503f23ae4e7c8292c59c93ba66d7a6a021d71a4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 22 May 2021 14:55:05 +0200 Subject: [PATCH 211/300] beeing safe with wrong / unknown setttings --- InvenTree/InvenTree/exchange.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index ce1db06711..8de0c9902f 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -13,8 +13,10 @@ def get_exchange_rate_backend(): if 'InvenTreeManualExchangeBackend' in inventree_settings.EXCHANGE_BACKEND: return InvenTreeManualExchangeBackend() - else: + elif 'InvenTreeFixerExchangeBackend' in inventree_settings.EXCHANGE_BACKEND: return InvenTreeFixerExchangeBackend() + else: + raise ImproperlyConfigured('Exchange Backend wrongly configured') class InvenTreeManualExchangeBackend(BaseExchangeBackend): From b1b974a1f611141dd5c8a751bcfc0b79264ef756 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 22 May 2021 14:55:41 +0200 Subject: [PATCH 212/300] safer check if fixer-backend is used --- InvenTree/InvenTree/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 48e42dd890..778316ddd5 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -959,7 +959,7 @@ class CurrencySettingsView(FormView): stored_rates = exchange_rate_backend.get_stored_rates() for field in form.fields: - if 'fixer' in exchange_rate_backend.name: + if exchange_rate_backend.name.startswith('fixer-'): # Disable all the fields form.fields[field].disabled = True form.fields[field].initial = clean_decimal(stored_rates.get(field, 0)) @@ -973,7 +973,7 @@ class CurrencySettingsView(FormView): # Get exchange rate backend exchange_rate_backend = self.get_exchange_rate_backend() - if 'fixer' in exchange_rate_backend.name: + if exchange_rate_backend.name.startswith('fixer-'): # Refresh rate from Fixer.IO API exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency) # Check if rates have been updated From 65aa46816815b0a0ffe6153513b6018f909432bb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 23 May 2021 21:14:43 +1000 Subject: [PATCH 213/300] Add backend for exchangerate.host --- InvenTree/InvenTree/exchange.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 06de4861ec..a4ac06e24a 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,4 +1,4 @@ -from djmoney.contrib.exchange.backends.base import BaseExchangeBackend +from djmoney.contrib.exchange.backends.base import BaseExchangeBackend, SimpleExchangeBackend class InvenTreeManualExchangeBackend(BaseExchangeBackend): @@ -19,3 +19,18 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): """ return {} + + +class ExchangeRateHostBackend(SimpleExchangeBackend): + """ + Backend for https://exchangerate.host/ + """ + + name = "exchangerate.host" + + def __init__(self): + self.url = "https://api.exchangerate.host/latest" + + def get_params(self): + # No API key is required + return {} From b803fbae72e8614f7f5bc42026cf6599cf71472f Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 00:18:04 +0200 Subject: [PATCH 214/300] remofing setting --- InvenTree/common/models.py | 7 ------- InvenTree/part/settings.py | 8 -------- InvenTree/part/test_part.py | 1 - InvenTree/templates/InvenTree/settings/part.html | 1 - 4 files changed, 17 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 04fd93188a..e499e9b801 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -217,13 +217,6 @@ class InvenTreeSetting(models.Model): 'validator': bool, }, - 'PART_SHOW_GRAPH': { - 'name': _('Show Price History Graph'), - 'description': _('Display the price history graph in the part pricing view'), - 'default': False, - 'validator': bool, - }, - 'REPORT_DEBUG_MODE': { 'name': _('Debug Mode'), 'description': _('Generate reports in debug mode (HTML output)'), diff --git a/InvenTree/part/settings.py b/InvenTree/part/settings.py index 671b7bf8f6..e345a9d88d 100644 --- a/InvenTree/part/settings.py +++ b/InvenTree/part/settings.py @@ -62,11 +62,3 @@ def part_trackable_default(): """ return InvenTreeSetting.get_setting('PART_TRACKABLE') - - -def part_show_graph(): - """ - Returns if the part pricing graph should be shown - """ - - return InvenTreeSetting.get_setting('PART_SHOW_GRAPH') diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 01e05f2710..cd8726ccf4 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -212,7 +212,6 @@ class PartSettingsTest(TestCase): self.assertFalse(part.settings.part_purchaseable_default()) self.assertFalse(part.settings.part_salable_default()) self.assertFalse(part.settings.part_trackable_default()) - self.assertFalse(part.settings.part_show_graph()) def test_initial(self): """ diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html index 6c2aff7711..e359acdfc2 100644 --- a/InvenTree/templates/InvenTree/settings/part.html +++ b/InvenTree/templates/InvenTree/settings/part.html @@ -21,7 +21,6 @@ {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_EDIT_IPN" %} {% include "InvenTree/settings/setting.html" with key="PART_SHOW_QUANTITY_IN_FORMS" icon="fa-hashtag" %} {% include "InvenTree/settings/setting.html" with key="PART_RECENT_COUNT" icon="fa-clock" %} - {% include "InvenTree/settings/setting.html" with key="PART_SHOW_GRAPH" icon="fa-chart-bar" %} {% include "InvenTree/settings/setting.html" with key="PART_TEMPLATE" icon="fa-clone" %} {% include "InvenTree/settings/setting.html" with key="PART_ASSEMBLY" icon="fa-tools" %} From 7c18ebbbe4594333525050b8f7f7bb46d55938fc Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 01:13:46 +0200 Subject: [PATCH 215/300] creating new tab --- InvenTree/part/templates/part/navbar.html | 6 + .../part/templates/part/order_prices.html | 219 ++++++++++++++++++ InvenTree/part/urls.py | 1 + InvenTree/part/views.py | 107 ++++++--- 4 files changed, 301 insertions(+), 32 deletions(-) create mode 100644 InvenTree/part/templates/part/order_prices.html diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index df49841e31..a2c8104486 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -69,6 +69,12 @@ {% endif %} {% if part.purchaseable and roles.purchase_order.view %} +
  • + + + {% trans "Order Price" %} + +
  • diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html new file mode 100644 index 0000000000..5bbd5d22ef --- /dev/null +++ b/InvenTree/part/templates/part/order_prices.html @@ -0,0 +1,219 @@ +{% extends "part/part_base.html" %} +{% load static %} +{% load i18n %} +{% load inventree_extras %} + +{% block menubar %} +{% include 'part/navbar.html' with tab='order-prices' %} +{% endblock %} + +{% block heading %} +{% trans "Order Price Information" %} +{% endblock %} + +{% block details %} + +
    + {% csrf_token %} + {% load crispy_forms_tags %} + {% crispy form %} +
    + + +{% if part.supplier_count > 0 %} +

    {% trans 'Supplier Pricing' %}

    + + {% if min_total_buy_price %} + + + + + + {% if quantity > 1 %} + + + + + + {% endif %} + {% else %} + + + + {% endif %} +
    {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_buy_price %}Max: {% include "price.html" with price=max_unit_buy_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_buy_price %}Max: {% include "price.html" with price=max_total_buy_price %}
    + {% trans 'No supplier pricing available' %} +
    +{% endif %} + +{% if part.bom_count > 0 %} +

    {% trans 'BOM Pricing' %}

    + + {% if min_total_bom_price %} + + + + + + {% if quantity > 1 %} + + + + + + {% endif %} + {% if part.has_complete_bom_pricing == False %} + + + + {% endif %} + {% else %} + + + + {% endif %} +
    {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_bom_price %}Max: {% include "price.html" with price=max_unit_bom_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_bom_price %}Max: {% include "price.html" with price=max_total_bom_price %}
    + {% trans 'Note: BOM pricing is incomplete for this part' %} +
    + {% trans 'No BOM pricing available' %} +
    +{% endif %} + +{% if total_part_price %} +

    {% trans 'Sale Price' %}

    + + + + + + + + + +
    {% trans 'Unit Cost' %}{% include "price.html" with price=unit_part_price %}
    {% trans 'Total Cost' %}{% include "price.html" with price=total_part_price %}
    +{% endif %} + + {% if min_unit_buy_price or min_unit_bom_price %} + {% else %} +
    + {% trans 'No pricing information is available for this part.' %} +
    + {% endif %} +
    + +{% if price_history %} +

    {% trans 'Stock Pricing' %}

    + {% if price_history|length > 1 %} +
    + +
    + {% else %} +
    + {% trans 'No stock pricing history is available for this part.' %} +
    + {% endif %} +{% endif %} +{% endblock %} + + + + +{% block js_ready %} + {{ block.super }} + + {% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} + + {% if price_history %} + var pricedata = { + labels: [ + {% for line in price_history %}'{{ line.date }}',{% endfor %} + ], + datasets: [{ + label: '{% trans "Single Price" %}', + backgroundColor: 'rgba(255, 99, 132, 0.2)', + borderColor: 'rgb(255, 99, 132)', + yAxisID: 'y', + data: [ + {% for line in price_history %}{{ line.price|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line' + }, + {% if 'price_diff' in price_history.0 %} + { + label: '{% trans "Single Price Difference" %}', + backgroundColor: 'rgba(68, 157, 68, 0.2)', + borderColor: 'rgb(68, 157, 68)', + yAxisID: 'y2', + data: [ + {% for line in price_history %}{{ line.price_diff|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line' + }, + { + label: '{% trans "Part Single Price" %}', + backgroundColor: 'rgba(70, 127, 155, 0.2)', + borderColor: 'rgb(70, 127, 155)', + yAxisID: 'y', + data: [ + {% for line in price_history %}{{ line.price_part|stringformat:".2f" }},{% endfor %} + ], + borderWidth: 1, + type: 'line' + }, + {% endif %} + { + label: '{% trans "Quantity" %}', + backgroundColor: 'rgba(255, 206, 86, 0.2)', + borderColor: 'rgb(255, 206, 86)', + yAxisID: 'y1', + data: [ + {% for line in price_history %}{{ line.qty|stringformat:"f" }},{% endfor %} + ], + borderWidth: 1 + }] + } + var ctx = document.getElementById('StockPriceChart'); + var StockPriceChart = new Chart(ctx, { + type: 'bar', + data: pricedata, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: {legend: {position: 'bottom'}}, + scales: { + y: { + type: 'linear', + position: 'left', + grid: {display: false}, + title: { + display: true, + text: '{% blocktrans %}Single Price - {{currency}}{% endblocktrans %}' + } + }, + y1: { + type: 'linear', + position: 'right', + grid: {display: false}, + titel: { + display: true, + text: '{% trans "Quantity" %}', + position: 'right' + } + }, + y2: { + type: 'linear', + position: 'left', + grid: {display: false}, + title: { + display: true, + text: '{% blocktrans %}Single Price Difference- {{currency}}{% endblocktrans %}' + } + } + }, + } + }); + {% endif %} + +{% endblock %} diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index c734b7f610..e53ce54782 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -59,6 +59,7 @@ part_detail_urls = [ url(r'^bom/?', views.PartDetail.as_view(template_name='part/bom.html'), name='part-bom'), url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'), url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'), + url(r'^order-prices/', views.PartPricingView.as_view(template_name='part/order_prices.html'), name='part-order-prices'), url(r'^manufacturers/?', views.PartDetail.as_view(template_name='part/manufacturer.html'), name='part-manufacturers'), url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'), url(r'^orders/?', views.PartDetail.as_view(template_name='part/orders.html'), name='part-orders'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index a2986fe869..63352c613b 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -784,6 +784,81 @@ class PartDetail(InvenTreeRoleMixin, DetailView): return context +class PartPricingView(PartDetail): + """ Detail view for Part object + """ + context_object_name = 'part' + template_name = 'part/order_prices.html' + form_class = part_forms.PartPriceForm + + # Add in some extra context information based on query params + def get_context_data(self, **kwargs): + """ Provide extra context data to template """ + context = super().get_context_data(**kwargs) + + ctx = self.get_pricing(self.get_quantity()) + ctx['form'] = self.form_class(initial=self.get_initials()) + + context.update(ctx) + return context + + def get_quantity(self): + """ Return set quantity in decimal format """ + return Decimal(self.request.POST.get('quantity', 1)) + + def get_part(self): + return self.get_object() + + def get_pricing(self, quantity=1, currency=None): + """ returns context with pricing information """ + ctx = PartPricing.get_pricing(self, quantity, currency) + part = self.get_part() + # Stock history + if part.total_stock > 1: + ret = [] + stock = part.stock_entries(include_variants=False, in_stock=True) # .order_by('purchase_order__date') + stock = stock.prefetch_related('purchase_order', 'supplier_part') + + for stock_item in stock: + if None in [stock_item.purchase_price, stock_item.quantity]: + continue + + # convert purchase price to current currency - only one currency in the graph + price = convert_money(stock_item.purchase_price, inventree_settings.currency_code_default()) + line = { + 'price': price.amount, + 'qty': stock_item.quantity + } + # Supplier Part Name # TODO use in graph + if stock_item.supplier_part: + line['name'] = stock_item.supplier_part.pretty_name + + if stock_item.supplier_part.unit_pricing and price: + line['price_diff'] = price.amount - stock_item.supplier_part.unit_pricing + line['price_part'] = stock_item.supplier_part.unit_pricing + + # set date for graph labels + if stock_item.purchase_order: + line['date'] = stock_item.purchase_order.issue_date.strftime('%d.%m.%Y') + else: + line['date'] = stock_item.tracking_info.first().date.strftime('%d.%m.%Y') + ret.append(line) + + ctx['price_history'] = ret + + return ctx + + def get_initials(self): + """ returns initials for form """ + return {'quantity': self.get_quantity()} + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + kwargs['object'] = self.object + ctx=self.get_context_data(**kwargs) + return self.get(request, context=ctx) + + class PartDetailFromIPN(PartDetail): slug_field = 'IPN' slug_url_kwarg = 'slug' @@ -2040,38 +2115,6 @@ class PartPricing(AjaxView): ctx['max_total_bom_price'] = max_bom_price ctx['max_unit_bom_price'] = max_unit_bom_price - # Stock history - if part_settings.part_show_graph and part.total_stock > 1: - ret = [] - stock = part.stock_entries(include_variants=False, in_stock=True) # .order_by('purchase_order__date') - stock = stock.prefetch_related('purchase_order', 'supplier_part') - - for stock_item in stock: - if None in [stock_item.purchase_price, stock_item.quantity]: - continue - - # convert purchase price to current currency - only one currency in the graph - price = convert_money(stock_item.purchase_price, inventree_settings.currency_code_default()) - line = { - 'price': price.amount, - 'qty': stock_item.quantity - } - # Supplier Part Name # TODO use in graph - if stock_item.supplier_part: - line['name'] = stock_item.supplier_part.pretty_name - - if stock_item.supplier_part.unit_pricing and price: - line['price_diff'] = price.amount - stock_item.supplier_part.unit_pricing - line['price_part'] = stock_item.supplier_part.unit_pricing - - # set date for graph labels - if stock_item.purchase_order: - line['date'] = stock_item.purchase_order.issue_date.strftime('%d.%m.%Y') - else: - line['date'] = stock_item.tracking_info.first().date.strftime('%d.%m.%Y') - ret.append(line) - - ctx['price_history'] = ret # part pricing information part_price = part.get_price(quantity) if part_price is not None: From 84d71d928fd7cea21efc3c0f8b0a2e835adbcade Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 01:14:15 +0200 Subject: [PATCH 216/300] removing new stuff in pricing modal --- .../part/templates/part/part_pricing.html | 128 +----------------- 1 file changed, 7 insertions(+), 121 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index e552d40024..49e37fe0ad 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -1,7 +1,6 @@ {% extends "modal_form.html" %} {% load i18n %} -{% load inventree_extras %} {% block pre_form_content %} @@ -88,124 +87,11 @@
    {% endif %} - {% if min_unit_buy_price or min_unit_bom_price %} - {% else %} -
    - {% trans 'No pricing information is available for this part.' %} -
    - {% endif %} -
    +{% if min_unit_buy_price or min_unit_bom_price %} +{% else %} +
    + {% trans 'No pricing information is available for this part.' %} +
    +{% endif %} +
    {% endblock %} - -{% block post_form_content %} - {% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} - {% settings_value "PART_SHOW_GRAPH" as show_graph %} - - {% if show_graph and price_history %} -

    {% trans 'Stock Pricing' %}

    - {% if price_history|length > 1 %} -
    - -
    -
    - {% blocktrans %}All prices are converted from their original currencies to {{currency}} at the current conversion-rate.{% endblocktrans %} -
    - - {% else %} -
    - {% trans 'No stock pricing history is available for this part.' %} -
    - {% endif %} - {% endif %} -{% endblock %} \ No newline at end of file From 25681fb805bab21ceb6b10d9dc34685975398891 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 01:30:37 +0200 Subject: [PATCH 217/300] style --- InvenTree/part/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 63352c613b..6c4b7ed342 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -42,7 +42,6 @@ from common.models import InvenTreeSetting from company.models import SupplierPart import common.settings as inventree_settings -import part.settings as part_settings from . import forms as part_forms from .bom import MakeBomTemplate, BomUploadManager, ExportBom, IsValidBOMFormat @@ -855,7 +854,7 @@ class PartPricingView(PartDetail): def post(self, request, *args, **kwargs): self.object = self.get_object() kwargs['object'] = self.object - ctx=self.get_context_data(**kwargs) + ctx = self.get_context_data(**kwargs) return self.get(request, context=ctx) From d5b2bfedbc8c34afcef342a30469baa3b6721f2d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 02:18:34 +0200 Subject: [PATCH 218/300] re-layouting tables --- .../part/templates/part/order_prices.html | 141 +++++++++--------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html index 5bbd5d22ef..299bc82468 100644 --- a/InvenTree/part/templates/part/order_prices.html +++ b/InvenTree/part/templates/part/order_prices.html @@ -1,6 +1,7 @@ {% extends "part/part_base.html" %} {% load static %} {% load i18n %} +{% load crispy_forms_tags %} {% load inventree_extras %} {% block menubar %} @@ -12,96 +13,94 @@ {% endblock %} {% block details %} +{% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} -
    - {% csrf_token %} - {% load crispy_forms_tags %} - {% crispy form %} -
    - +{% crispy form %} +
    +

    {% trans "Pricing ranges" %}

    + {% if part.supplier_count > 0 %} -

    {% trans 'Supplier Pricing' %}

    -
    {% if min_total_buy_price %} - - - - - - {% if quantity > 1 %} - - - - - - {% endif %} + + + + + + + {% if quantity > 1 %} + + + + + + + {% endif %} {% else %} - - - + + + {% endif %} -
    {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_buy_price %}Max: {% include "price.html" with price=max_unit_buy_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_buy_price %}Max: {% include "price.html" with price=max_total_buy_price %}
    {% trans 'Supplier Pricing' %}{% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_buy_price %}Max: {% include "price.html" with price=max_unit_buy_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_buy_price %}Max: {% include "price.html" with price=max_total_buy_price %}
    - {% trans 'No supplier pricing available' %} -
    + {% trans 'No supplier pricing available' %} +
    {% endif %} {% if part.bom_count > 0 %} -

    {% trans 'BOM Pricing' %}

    - {% if min_total_bom_price %} - - - - - - {% if quantity > 1 %} - - - - - - {% endif %} - {% if part.has_complete_bom_pricing == False %} - - - - {% endif %} + + + + + + + {% if quantity > 1 %} + + + + + + + {% endif %} + {% if part.has_complete_bom_pricing == False %} + + + + {% endif %} {% else %} - - - + + + {% endif %} -
    {% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_bom_price %}Max: {% include "price.html" with price=max_unit_bom_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_bom_price %}Max: {% include "price.html" with price=max_total_bom_price %}
    - {% trans 'Note: BOM pricing is incomplete for this part' %} -
    {% trans 'BOM Pricing' %}{% trans 'Unit Cost' %}Min: {% include "price.html" with price=min_unit_bom_price %}Max: {% include "price.html" with price=max_unit_bom_price %}
    {% trans 'Total Cost' %}Min: {% include "price.html" with price=min_total_bom_price %}Max: {% include "price.html" with price=max_total_bom_price %}
    + {% trans 'Note: BOM pricing is incomplete for this part' %} +
    - {% trans 'No BOM pricing available' %} -
    + {% trans 'No BOM pricing available' %} +
    {% endif %} {% if total_part_price %} -

    {% trans 'Sale Price' %}

    - - - - - - - - - -
    {% trans 'Unit Cost' %}{% include "price.html" with price=unit_part_price %}
    {% trans 'Total Cost' %}{% include "price.html" with price=total_part_price %}
    + + {% trans 'Sale Price' %} + {% trans 'Unit Cost' %} + {% include "price.html" with price=unit_part_price %} + + + + {% trans 'Total Cost' %} + {% include "price.html" with price=total_part_price %} + {% endif %} + - {% if min_unit_buy_price or min_unit_bom_price %} - {% else %} -
    - {% trans 'No pricing information is available for this part.' %} -
    - {% endif %} -
    +{% if min_unit_buy_price or min_unit_bom_price %} +{% else %} +
    + {% trans 'No pricing information is available for this part.' %} +
    +{% endif %} +
    {% if price_history %} +

    {% trans 'Stock Pricing' %}

    {% if price_history|length > 1 %}
    From fe8e03c666ad86d9d8f4cb60e97a61851618cf76 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 15:46:11 +0200 Subject: [PATCH 219/300] additional information for graph --- InvenTree/part/templates/part/order_prices.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html index 299bc82468..7d99d7a821 100644 --- a/InvenTree/part/templates/part/order_prices.html +++ b/InvenTree/part/templates/part/order_prices.html @@ -101,7 +101,8 @@ {% if price_history %}
    -

    {% trans 'Stock Pricing' %}

    +

    {% trans 'Stock Pricing' %}

    {% if price_history|length > 1 %}
    From 206bab137bb1f2892a4cab90055490da7714e717 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 17:39:32 +0200 Subject: [PATCH 220/300] refactor --- .../part/templates/part/order_prices.html | 46 ++----------------- InvenTree/templates/js/part.js | 43 +++++++++++++++++ 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html index 7d99d7a821..8efcf2994d 100644 --- a/InvenTree/part/templates/part/order_prices.html +++ b/InvenTree/part/templates/part/order_prices.html @@ -129,7 +129,7 @@ the part single price shown is the current price for that supplier part"> Date: Mon, 24 May 2021 19:14:38 +0200 Subject: [PATCH 221/300] added in randomColor for dynamic color gen --- InvenTree/InvenTree/static/script/randomColor.min.js | 1 + InvenTree/templates/base.html | 1 + 2 files changed, 2 insertions(+) create mode 100644 InvenTree/InvenTree/static/script/randomColor.min.js diff --git a/InvenTree/InvenTree/static/script/randomColor.min.js b/InvenTree/InvenTree/static/script/randomColor.min.js new file mode 100644 index 0000000000..218a0f65b0 --- /dev/null +++ b/InvenTree/InvenTree/static/script/randomColor.min.js @@ -0,0 +1 @@ +!function(r,e){var n;"object"==typeof exports?(n=e(),"object"==typeof module&&module&&module.exports&&(exports=module.exports=n),exports.randomColor=n):"function"==typeof define&&define.amd?define([],e):r.randomColor=e()}(this,function(){var o=null,s={};r("monochrome",null,[[0,0],[100,0]]),r("red",[-26,18],[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]),r("orange",[18,46],[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]),r("yellow",[46,62],[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]),r("green",[62,178],[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]),r("blue",[178,257],[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]),r("purple",[257,282],[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]),r("pink",[282,334],[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]);var i=[],f=function(r){if(void 0!==(r=r||{}).seed&&null!==r.seed&&r.seed===parseInt(r.seed,10))o=r.seed;else if("string"==typeof r.seed)o=function(r){for(var e=0,n=0;n!==r.length&&!(e>=Number.MAX_SAFE_INTEGER);n++)e+=r.charCodeAt(n);return e}(r.seed);else{if(void 0!==r.seed&&null!==r.seed)throw new TypeError("The seed value must be an integer or string");o=null}var e,n;if(null===r.count||void 0===r.count)return function(r,e){switch(e.format){case"hsvArray":return r;case"hslArray":return d(r);case"hsl":var n=d(r);return"hsl("+n[0]+", "+n[1]+"%, "+n[2]+"%)";case"hsla":var t=d(r),a=e.alpha||Math.random();return"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+a+")";case"rgbArray":return h(r);case"rgb":return"rgb("+h(r).join(", ")+")";case"rgba":var u=h(r),a=e.alpha||Math.random();return"rgba("+u.join(", ")+", "+a+")";default:return function(r){var e=h(r);function n(r){var e=r.toString(16);return 1==e.length?"0"+e:e}return"#"+n(e[0])+n(e[1])+n(e[2])}(r)}}([e=function(r){{if(0a.length;)o&&r.seed&&(r.seed+=1),a.push(f(r));return r.count=t,a};function l(r){for(var e in 334<=r&&r<=360&&(r-=360),s){var n=s[e];if(n.hueRange&&r>=n.hueRange[0]&&r<=n.hueRange[1])return s[e]}return"Color not found"}function c(r){if(null===o){var e=Math.random();return e+=.618033988749895,e%=1,Math.floor(r[0]+e*(r[1]+1-r[0]))}var n=r[1]||1,t=r[0]||0,a=(o=(9301*o+49297)%233280)/233280;return Math.floor(t+a*(n-t))}function r(r,e,n){var t=n[0][0],a=n[n.length-1][0],u=n[n.length-1][1],o=n[0][1];s[r]={hueRange:e,lowerBounds:n,saturationRange:[t,a],brightnessRange:[u,o]}}function h(r){var e=r[0];0===e&&(e=1),360===e&&(e=359),e/=360;var n=r[1]/100,t=r[2]/100,a=Math.floor(6*e),u=6*e-a,o=t*(1-n),s=t*(1-u*n),i=t*(1-(1-u)*n),f=256,l=256,c=256;switch(a){case 0:f=t,l=i,c=o;break;case 1:f=s,l=t,c=o;break;case 2:f=o,l=t,c=i;break;case 3:f=o,l=s,c=t;break;case 4:f=i,l=o,c=t;break;case 5:f=t,l=o,c=s}return[Math.floor(255*f),Math.floor(255*l),Math.floor(255*c)]}function g(r){r=3===(r=r.replace(/^#/,"")).length?r.replace(/(.)/g,"$1$1"):r;var e=parseInt(r.substr(0,2),16)/255,n=parseInt(r.substr(2,2),16)/255,t=parseInt(r.substr(4,2),16)/255,a=Math.max(e,n,t),u=a-Math.min(e,n,t),o=a?u/a:0;switch(a){case e:return[(n-t)/u%6*60||0,o,a];case n:return[60*((t-e)/u+2)||0,o,a];case t:return[60*((e-n)/u+4)||0,o,a]}}function d(r){var e=r[0],n=r[1]/100,t=r[2]/100,a=(2-n)*t;return[e,Math.round(n*t/(a<1?a:2-a)*1e4)/100,a/2*100]}return f}); \ No newline at end of file diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index d1dc1b2bfa..07b1a1d34b 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -140,6 +140,7 @@ + From b4c9edcd270a50658b1b6e989c5ab076bdba151f Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 24 May 2021 22:31:33 +0200 Subject: [PATCH 222/300] bom-price ranges as pie-chart --- .../part/templates/part/order_prices.html | 35 ++++++++++++++++--- InvenTree/part/views.py | 13 +++++++ InvenTree/templates/js/part.js | 16 ++++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html index 8efcf2994d..6c5b2173bf 100644 --- a/InvenTree/part/templates/part/order_prices.html +++ b/InvenTree/part/templates/part/order_prices.html @@ -97,7 +97,16 @@ {% trans 'No pricing information is available for this part.' %}
    {% endif %} -
  • +
    +{% if part.bom_count > 0 %} +
    +

    {% trans 'BOM Pricing' %}

    +
    + +
    +
    +{% endif %} +
    {% if price_history %}
    @@ -122,7 +131,6 @@ the part single price shown is the current price for that supplier part"> Date: Mon, 24 May 2021 22:45:00 +0200 Subject: [PATCH 223/300] style --- InvenTree/part/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index c237d6b249..24fc73fd3e 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -847,15 +847,15 @@ class PartPricingView(PartDetail): # BOM Information for Pie-Chart bom_items = [{'name': str(a.sub_part), 'price': a.sub_part.get_price_range(quantity), 'q': a.quantity} for a in part.bom_items.all()] - if [True for a in bom_items if len(set(a['price']))==2]: + if [True for a in bom_items if len(set(a['price'])) == 2]: ctx['bom_parts'] = [{ 'name': a['name'], - 'min_price': str((a['price'][0] * a['q'])/ quantity), + 'min_price': str((a['price'][0] * a['q']) / quantity), 'max_price': str((a['price'][1] * a['q']) / quantity)} for a in bom_items] ctx['bom_pie_min'] = True else: ctx['bom_parts'] = [{ - 'name':a['name'], + 'name': a['name'], 'price': str((a['price'][0] * a['q']) / quantity)} for a in bom_items] return ctx From ff80c722fb2023d955e8fc15621db62953d92bc8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 25 May 2021 09:32:21 +1000 Subject: [PATCH 224/300] Docker: Add parent directories if they do not exist --- docker/Dockerfile | 3 ++- docker/start_dev_server.sh | 4 ++-- docker/start_prod_server.sh | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index ea70d9f994..5c5d1dc32a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -41,9 +41,10 @@ LABEL org.label-schema.schema-version="1.0" \ # Create user account RUN addgroup -S inventreegroup && adduser -S inventree -G inventreegroup + WORKDIR ${INVENTREE_HOME} -RUN mkdir ${INVENTREE_STATIC_ROOT} +RUN mkdir -p ${INVENTREE_STATIC_ROOT} # Install required system packages RUN apk add --no-cache git make bash \ diff --git a/docker/start_dev_server.sh b/docker/start_dev_server.sh index 0c1564076a..d4e33a79a5 100644 --- a/docker/start_dev_server.sh +++ b/docker/start_dev_server.sh @@ -3,12 +3,12 @@ # Create required directory structure (if it does not already exist) if [[ ! -d "$INVENTREE_STATIC_ROOT" ]]; then echo "Creating directory $INVENTREE_STATIC_ROOT" - mkdir $INVENTREE_STATIC_ROOT + mkdir -p $INVENTREE_STATIC_ROOT fi if [[ ! -d "$INVENTREE_MEDIA_ROOT" ]]; then echo "Creating directory $INVENTREE_MEDIA_ROOT" - mkdir $INVENTREE_MEDIA_ROOT + mkdir -p $INVENTREE_MEDIA_ROOT fi # Check if "config.yaml" has been copied into the correct location diff --git a/docker/start_prod_server.sh b/docker/start_prod_server.sh index 2767e844d6..2e5acb5c9d 100644 --- a/docker/start_prod_server.sh +++ b/docker/start_prod_server.sh @@ -3,12 +3,12 @@ # Create required directory structure (if it does not already exist) if [[ ! -d "$INVENTREE_STATIC_ROOT" ]]; then echo "Creating directory $INVENTREE_STATIC_ROOT" - mkdir $INVENTREE_STATIC_ROOT + mkdir -p $INVENTREE_STATIC_ROOT fi if [[ ! -d "$INVENTREE_MEDIA_ROOT" ]]; then echo "Creating directory $INVENTREE_MEDIA_ROOT" - mkdir $INVENTREE_MEDIA_ROOT + mkdir -p $INVENTREE_MEDIA_ROOT fi # Check if "config.yaml" has been copied into the correct location From 619cba6007c92c0ac75d6c2c755e8e7fdea58df5 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 25 May 2021 10:37:53 +1000 Subject: [PATCH 225/300] Currency: Use ExchangeRateHost backend by default, rather than fixer.io - No longer support fixer.io as it requires an API key and does not support "base" currency --- InvenTree/InvenTree/tasks.py | 10 ++-------- InvenTree/common/models.py | 6 ------ InvenTree/templates/InvenTree/settings/global.html | 1 - 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index b81b4e6de4..e9e37e63a3 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -169,18 +169,12 @@ def update_exchange_rates(): try: import common.models from django.conf import settings - from djmoney.contrib.exchange.backends import FixerBackend + from InvenTree.exchange import ExchangeRateHostBackend except AppRegistryNotReady: # Apps not yet loaded! return - fixer_api_key = common.models.InvenTreeSetting.get_setting('INVENTREE_FIXER_API_KEY', '').strip() - - if not fixer_api_key: - # API key not provided - return - - backend = FixerBackend(access_key=fixer_api_key) + backend = ExchangeRateHostBackend() currencies = ','.join(settings.CURRENCIES) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index e499e9b801..99712b2a93 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -87,12 +87,6 @@ class InvenTreeSetting(models.Model): 'choices': djmoney.settings.CURRENCY_CHOICES, }, - 'INVENTREE_FIXER_API_KEY': { - 'name': _('fixer.io API key'), - 'description': _('API key for fixer.io currency conversion service'), - 'default': '', - }, - 'INVENTREE_DOWNLOAD_FROM_URL': { 'name': _('Download from URL'), 'description': _('Allow download of remote images and files from external URL'), diff --git a/InvenTree/templates/InvenTree/settings/global.html b/InvenTree/templates/InvenTree/settings/global.html index 5c5dccfb2a..a0347490d0 100644 --- a/InvenTree/templates/InvenTree/settings/global.html +++ b/InvenTree/templates/InvenTree/settings/global.html @@ -20,7 +20,6 @@ {% include "InvenTree/settings/setting.html" with key="INVENTREE_BASE_URL" icon="fa-globe" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_COMPANY_NAME" icon="fa-building" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} - {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DOWNLOAD_FROM_URL" icon="fa-cloud-download-alt" %} From 0a26a069092e3a0d0f6a0ebce929c38ac174dba6 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 25 May 2021 10:46:30 +1000 Subject: [PATCH 226/300] Use INVENTREE_DEFAULT_CURRENCY as specified base currency --- InvenTree/InvenTree/settings.py | 4 +--- InvenTree/InvenTree/tasks.py | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 5cf0b0c544..f0a3312b39 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -513,9 +513,7 @@ CURRENCIES = CONFIG.get( ], ) -BASE_CURRENCY = CONFIG.get('base_currency', 'USD') - -EXCHANGE_BACKEND = 'InvenTree.exchange.InvenTreeManualExchangeBackend' +EXCHANGE_BACKEND = 'InvenTree.exchange.ExchangeRateHostBackend' # Extract email settings from the config file email_config = CONFIG.get('email', {}) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index e9e37e63a3..ad33232fe0 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -175,10 +175,13 @@ def update_exchange_rates(): return backend = ExchangeRateHostBackend() + print(f"Updating exchange rates from {backend.url}") currencies = ','.join(settings.CURRENCIES) - base = settings.BASE_CURRENCY + base = common.models.InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') + + print(f"Using base currency '{base}'") backend.update_rates(base_currency=base, symbols=currencies) From 93bfe4c5f11d05e873629d4427ae13fae3d0b205 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 25 May 2021 11:19:07 -0400 Subject: [PATCH 227/300] Added 'Custom Exchange Rate' boolea setting Removed Fixer.io exchange rate backend --- InvenTree/InvenTree/exchange.py | 60 +++++-------------- InvenTree/InvenTree/settings.py | 2 - InvenTree/InvenTree/tasks.py | 7 +-- InvenTree/InvenTree/views.py | 6 +- InvenTree/common/models.py | 7 +++ InvenTree/config_template.yaml | 7 --- .../InvenTree/settings/currencies.html | 6 +- 7 files changed, 29 insertions(+), 66 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index 2a2d287e1c..0a75436b1e 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -1,7 +1,5 @@ -from django.core.exceptions import ImproperlyConfigured from django.conf import settings as inventree_settings -from djmoney import settings as djmoney_settings from djmoney.contrib.exchange.backends.base import BaseExchangeBackend from djmoney.contrib.exchange.models import Rate @@ -11,12 +9,12 @@ from common.models import InvenTreeSetting def get_exchange_rate_backend(): """ Return the exchange rate backend set by user """ - if 'InvenTreeManualExchangeBackend' in inventree_settings.EXCHANGE_BACKEND: + custom = InvenTreeSetting.get_setting('CUSTOM_EXCHANGE_RATES', False) + + if custom: return InvenTreeManualExchangeBackend() - elif 'InvenTreeFixerExchangeBackend' in inventree_settings.EXCHANGE_BACKEND: - return InvenTreeFixerExchangeBackend() else: - raise ImproperlyConfigured('Exchange Backend wrongly configured') + return ExchangeRateHostBackend() class InvenTreeManualExchangeBackend(BaseExchangeBackend): @@ -30,13 +28,14 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): name = 'inventree' url = None + custom_rates = True base_currency = None currencies = [] def update_default_currency(self): """ Update to base currency """ - self.base_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', inventree_settings.BASE_CURRENCY) + self.base_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', 'USD') def __init__(self, url=None): """ Overrides init to update url, base currency and currencies """ @@ -73,39 +72,23 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend): return stored_rates -class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): +class ExchangeRateHostBackend(InvenTreeManualExchangeBackend): """ - Backend for updating currency exchange rates using Fixer.IO API + Backend for https://exchangerate.host/ """ - name = 'fixer' - access_key = None - - def get_api_key(self): - """ Get API key from global settings """ - - fixer_api_key = InvenTreeSetting.get_setting('INVENTREE_FIXER_API_KEY', '').strip() - - if not fixer_api_key: - # API key not provided - return None - - self.access_key = fixer_api_key + name = "exchangerate.host" def __init__(self): - """ Override init to get access_key from global settings """ + self.url = "https://api.exchangerate.host/latest" - self.get_api_key() + self.custom_rates = False - if self.access_key is None: - raise ImproperlyConfigured("fixer.io API key is needed to use InvenTreeFixerExchangeBackend") - - super().__init__(url=djmoney_settings.FIXER_URL) + super().__init__(url=self.url) def get_params(self): - """ Returns parameters (access key) """ - - return {"access_key": self.access_key} + # No API key is required + return {} def update_rates(self, base_currency=None): """ Override update_rates method using currencies found in the settings @@ -135,18 +118,3 @@ class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend): pass return {} - - -class ExchangeRateHostBackend(SimpleExchangeBackend): - """ - Backend for https://exchangerate.host/ - """ - - name = "exchangerate.host" - - def __init__(self): - self.url = "https://api.exchangerate.host/latest" - - def get_params(self): - # No API key is required - return {} diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index f0a3312b39..afa43396f5 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -513,8 +513,6 @@ CURRENCIES = CONFIG.get( ], ) -EXCHANGE_BACKEND = 'InvenTree.exchange.ExchangeRateHostBackend' - # Extract email settings from the config file email_config = CONFIG.get('email', {}) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index ad33232fe0..365a94fd07 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -163,12 +163,11 @@ def check_for_updates(): def update_exchange_rates(): """ - If an API key for fixer.io has been provided, attempt to update currency exchange rates + Update currency exchange rates """ try: import common.models - from django.conf import settings from InvenTree.exchange import ExchangeRateHostBackend except AppRegistryNotReady: # Apps not yet loaded! @@ -177,13 +176,11 @@ def update_exchange_rates(): backend = ExchangeRateHostBackend() print(f"Updating exchange rates from {backend.url}") - currencies = ','.join(settings.CURRENCIES) - base = common.models.InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY') print(f"Using base currency '{base}'") - backend.update_rates(base_currency=base, symbols=currencies) + backend.update_rates(base_currency=base) def send_email(subject, body, recipients, from_email=None): diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 778316ddd5..a18845bf02 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -944,6 +944,8 @@ class CurrencySettingsView(FormView): context['default_currency'] = exchange_rate_backend.base_currency + context['custom_rates'] = exchange_rate_backend.custom_rates + context['exchange_backend'] = exchange_rate_backend.name return context @@ -959,7 +961,7 @@ class CurrencySettingsView(FormView): stored_rates = exchange_rate_backend.get_stored_rates() for field in form.fields: - if exchange_rate_backend.name.startswith('fixer-'): + if not exchange_rate_backend.custom_rates: # Disable all the fields form.fields[field].disabled = True form.fields[field].initial = clean_decimal(stored_rates.get(field, 0)) @@ -973,7 +975,7 @@ class CurrencySettingsView(FormView): # Get exchange rate backend exchange_rate_backend = self.get_exchange_rate_backend() - if exchange_rate_backend.name.startswith('fixer-'): + if not exchange_rate_backend.custom_rates: # Refresh rate from Fixer.IO API exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency) # Check if rates have been updated diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 99712b2a93..74c6c82b41 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -87,6 +87,13 @@ class InvenTreeSetting(models.Model): 'choices': djmoney.settings.CURRENCY_CHOICES, }, + 'CUSTOM_EXCHANGE_RATES': { + 'name': _('Custom Exchange Rates'), + 'description': _('Enable custom exchange rates'), + 'validator': bool, + 'default': False, + }, + 'INVENTREE_DOWNLOAD_FROM_URL': { 'name': _('Download from URL'), 'description': _('Allow download of remote images and files from external URL'), diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 7d301934f0..87dfb6b545 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -62,13 +62,6 @@ currencies: - JPY - NZD - USD -# Define base currency (can also be defined in the global settings) -# base_currency: USD -# Define exchange backend -# Choices are: -# - InvenTreeManualExchangeBackend -# - InvenTreeFixerExchangeBackend -exchange_backend: InvenTreeManualExchangeBackend # Email backend configuration # Ref: https://docs.djangoproject.com/en/dev/topics/email/ diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index d9b046b9f5..b6cf9fea81 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -16,9 +16,7 @@ {% include "InvenTree/settings/header.html" %} {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} - {% if 'fixer' in exchange_backend %} - {% include "InvenTree/settings/setting.html" with key="INVENTREE_FIXER_API_KEY" icon="fa-key" %} - {% endif %} + {% include "InvenTree/settings/setting.html" with key="CUSTOM_EXCHANGE_RATES" icon="fa-edit" %} @@ -33,7 +31,7 @@ {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} - {% if 'fixer' in exchange_backend %} + {% if custom_rates is False %} {% else %} From b04ad48178f72fabed21bb6ac7255f716095f200 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 25 May 2021 11:39:04 -0400 Subject: [PATCH 228/300] Fixed test using manual exchange backend, template update --- InvenTree/company/tests.py | 4 ++-- InvenTree/templates/InvenTree/settings/currencies.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/company/tests.py b/InvenTree/company/tests.py index e07516e180..2c6e722440 100644 --- a/InvenTree/company/tests.py +++ b/InvenTree/company/tests.py @@ -11,7 +11,7 @@ from .models import Company, Contact, ManufacturerPart, SupplierPart from .models import rename_company_image from part.models import Part -from InvenTree.exchange import get_exchange_rate_backend +from InvenTree.exchange import InvenTreeManualExchangeBackend from djmoney.contrib.exchange.models import Rate @@ -42,7 +42,7 @@ class CompanySimpleTest(TestCase): self.zergm312 = SupplierPart.objects.get(SKU='ZERGM312') # Exchange rate backend - backend = get_exchange_rate_backend() + backend = InvenTreeManualExchangeBackend() backend.update_rates(base_currency=backend.base_currency) Rate.objects.create( diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index b6cf9fea81..dd47bc6cdd 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -45,7 +45,7 @@ {{ block.super }} {% if api_rates_success is False %} - var alert_msg = {% blocktrans %}"Failed to refresh exchange rates. Verify your API key and/or subscription plan" {% endblocktrans %}; + var alert_msg = {% blocktrans %}"Failed to refresh exchange rates" {% endblocktrans %}; showAlertOrCache("alert-danger", alert_msg, null, 5000); {% endif %} From c2fe5e08b4bb52277050309d98596f275b5ef040 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 27 May 2021 12:35:55 +1000 Subject: [PATCH 229/300] Expand possibilities for variant conversion - Ref get_conversion_options --- InvenTree/part/models.py | 53 +++++++++++++++++++ InvenTree/part/templates/part/part_base.html | 5 ++ .../stock/templates/stock/item_base.html | 2 +- InvenTree/stock/views.py | 2 +- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 3c8e65bca7..7db998ab3d 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -1861,6 +1861,59 @@ class Part(MPTTModel): return self.get_descendants(include_self=False) + @property + def can_convert(self): + """ + Check if this Part can be "converted" to a different variant: + + It can be converted if: + + a) It has non-virtual variant parts underneath it + b) It has non-virtual template parts above it + c) It has non-virtual sibling variants + + """ + + return self.get_conversion_options().count() > 0 + + def get_conversion_options(self): + """ + Return options for converting this part to a "variant" within the same tree + + a) Variants underneath this one + b) Immediate parent + c) Siblings + """ + + parts = [] + + # Child parts + children = self.get_descendants(include_self=False) + + for child in children: + parts.append(child) + + # Immediate parent + if self.variant_of: + parts.append(self.variant_of) + + siblings = self.get_siblings(include_self=False) + + for sib in siblings: + parts.append(sib) + + filtered_parts = Part.objects.filter(pk__in=[part.pk for part in parts]) + + # Ensure this part is not in the queryset, somehow + filtered_parts = filtered_parts.exclude(pk=self.pk) + + filtered_parts = filtered_parts.filter( + active=True, + virtual=False, + ) + + return filtered_parts + def get_related_parts(self): """ Return list of tuples for all related parts: - first value is PartRelated object diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index f2f1f6557a..ec296d4174 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -102,6 +102,11 @@
    + {% if part.virtual %} +
    + {% trans "This is a virtual part" %} +
    + {% endif %} {% if part.variant_of %}
    {% object_link 'part-variants' part.variant_of.id part.variant_of.full_name as link %} diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index da770bab48..991bdee41c 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -139,7 +139,7 @@
    {% endif %} From 608547867290cbc29c47372580948b3cc15e5572 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 27 May 2021 16:34:37 +1000 Subject: [PATCH 234/300] Simplify settings view - Show various currency exchange rates - Button to "refresh now" --- InvenTree/InvenTree/forms.py | 34 ----- InvenTree/InvenTree/urls.py | 20 +-- InvenTree/InvenTree/views.py | 139 +++++++----------- .../InvenTree/settings/currencies.html | 59 ++++---- 4 files changed, 92 insertions(+), 160 deletions(-) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 488e982ddc..d843c1ddef 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -16,8 +16,6 @@ from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppende from common.models import ColorTheme from part.models import PartCategory -from .exchange import InvenTreeManualExchangeBackend - class HelperForm(forms.ModelForm): """ Provides simple integration of crispy_forms extension. """ @@ -240,35 +238,3 @@ class SettingCategorySelectForm(forms.ModelForm): css_class='row', ), ) - - -class SettingExchangeRatesForm(forms.Form): - """ Form for displaying and setting currency exchange rates manually """ - - def __init__(self, *args, **kwargs): - - super().__init__(*args, **kwargs) - - exchange_rate_backend = InvenTreeManualExchangeBackend() - - # Update default currency (in case it has changed) - exchange_rate_backend.update_default_currency() - - for currency in exchange_rate_backend.currencies: - if currency != exchange_rate_backend.base_currency: - # Set field name - field_name = currency - # Set field input box - self.fields[field_name] = forms.CharField( - label=field_name, - required=False, - widget=forms.NumberInput(attrs={ - 'name': field_name, - 'class': 'numberinput', - 'style': 'width: 200px;', - 'type': 'number', - 'min': '0', - 'step': 'any', - 'value': 0, - }) - ) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 88ee554203..bce493fb23 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -39,6 +39,7 @@ from rest_framework.documentation import include_docs_urls from .views import IndexView, SearchView, DatabaseStatsView from .views import SettingsView, EditUserView, SetPasswordView +from .views import CurrencySettingsView, CurrencyRefreshView from .views import AppearanceSelectView, SettingCategorySelectView from .views import DynamicJsView @@ -82,15 +83,16 @@ settings_urls = [ url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'), url(r'^i18n/?', include('django.conf.urls.i18n')), - url(r'^global/?', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'), - url(r'^report/?', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'), - url(r'^category/?', SettingCategorySelectView.as_view(), name='settings-category'), - url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'), - url(r'^stock/?', SettingsView.as_view(template_name='InvenTree/settings/stock.html'), name='settings-stock'), - url(r'^build/?', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'), - url(r'^purchase-order/?', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'), - url(r'^sales-order/?', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'), - url(r'^currencies/?', SettingsView.as_view(template_name='InvenTree/settings/currencies.html'), name='settings-currencies'), + url(r'^global/', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'), + url(r'^report/', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'), + url(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'), + url(r'^part/', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'), + url(r'^stock/', SettingsView.as_view(template_name='InvenTree/settings/stock.html'), name='settings-stock'), + url(r'^build/', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'), + url(r'^purchase-order/', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'), + url(r'^sales-order/', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'), + url(r'^currencies/', CurrencySettingsView.as_view(), name='settings-currencies'), + url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'), url(r'^(?P\d+)/edit/', SettingEdit.as_view(), name='setting-edit'), diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index a18845bf02..4189def492 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -12,12 +12,15 @@ from django.utils.translation import gettext_lazy as _ from django.template.loader import render_to_string from django.http import JsonResponse, HttpResponseRedirect from django.urls import reverse_lazy +from django.conf import settings from django.contrib.auth.mixins import PermissionRequiredMixin from django.views import View from django.views.generic import ListView, DetailView, CreateView, FormView, DeleteView, UpdateView -from django.views.generic.base import TemplateView +from django.views.generic.base import RedirectView, TemplateView + +from djmoney.contrib.exchange.models import ExchangeBackend, Rate from part.models import Part, PartCategory from stock.models import StockLocation, StockItem @@ -25,11 +28,11 @@ from common.models import InvenTreeSetting, ColorTheme from users.models import check_user_role, RuleSet from InvenTree.helpers import clean_decimal +import InvenTree.tasks + from .forms import DeleteForm, EditUserForm, SetPasswordForm from .forms import ColorThemeSelectForm, SettingCategorySelectForm -from .forms import SettingExchangeRatesForm from .helpers import str2bool -from .exchange import get_exchange_rate_backend from rest_framework import views @@ -772,6 +775,50 @@ class SettingsView(TemplateView): return ctx + +class CurrencyRefreshView(RedirectView): + + url = reverse_lazy("settings-currencies") + + def post(self, request, *args, **kwargs): + """ + On a POST request we will attempt to refresh the exchange rates + """ + + print("POST!") + + # Will block for a little bit + InvenTree.tasks.update_exchange_rates() + + return self.get(request, *args, **kwargs) + + +class CurrencySettingsView(TemplateView): + """ + View for configuring currency settings + """ + + template_name = "InvenTree/settings/currencies.html" + + def get_context_data(self, **kwargs): + + ctx = super().get_context_data(**kwargs).copy() + + ctx['settings'] = InvenTreeSetting.objects.all().order_by('key') + ctx["base_currency"] = settings.BASE_CURRENCY + ctx["currencies"] = settings.CURRENCIES + + ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange") + + # When were the rates last updated? + try: + backend = ExchangeBackend.objects.get(name='InvenTreeExchange') + ctx["rates_updated"] = backend.last_update + except: + ctx["rates_updated"] = None + + return ctx + class AppearanceSelectView(FormView): """ View for selecting a color theme """ @@ -911,89 +958,3 @@ class DatabaseStatsView(AjaxView): """ return ctx - - -class CurrencySettingsView(FormView): - - form_class = SettingExchangeRatesForm - template_name = 'InvenTree/settings/currencies.html' - success_url = reverse_lazy('settings-currencies') - - exchange_rate_backend = None - - def get_exchange_rate_backend(self): - - if not self.exchange_rate_backend: - self.exchange_rate_backend = get_exchange_rate_backend() - - return self.exchange_rate_backend - - def get_context_data(self, **kwargs): - - context = super().get_context_data(**kwargs) - - # Set default API result - if 'api_rates_success' not in context: - context['default_currency'] = True - else: - # Update form - context['form'] = self.get_form() - - # Get exchange rate backend - exchange_rate_backend = self.get_exchange_rate_backend() - - context['default_currency'] = exchange_rate_backend.base_currency - - context['custom_rates'] = exchange_rate_backend.custom_rates - - context['exchange_backend'] = exchange_rate_backend.name - - return context - - def get_form(self): - - form = super().get_form() - - # Get exchange rate backend - exchange_rate_backend = self.get_exchange_rate_backend() - - # Get stored exchange rates - stored_rates = exchange_rate_backend.get_stored_rates() - - for field in form.fields: - if not exchange_rate_backend.custom_rates: - # Disable all the fields - form.fields[field].disabled = True - form.fields[field].initial = clean_decimal(stored_rates.get(field, 0)) - - return form - - def post(self, request, *args, **kwargs): - - form = self.get_form() - - # Get exchange rate backend - exchange_rate_backend = self.get_exchange_rate_backend() - - if not exchange_rate_backend.custom_rates: - # Refresh rate from Fixer.IO API - exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency) - # Check if rates have been updated - if not exchange_rate_backend.get_stored_rates(): - # Update context - context = {'api_rates_success': False} - # Return view with updated context - return self.render_to_response(self.get_context_data(form=form, **context)) - else: - # Update rates from form - manual_rates = {} - - if form.is_valid(): - for field, value in form.cleaned_data.items(): - manual_rates[field] = clean_decimal(value) - - exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency, **{'rates': manual_rates}) - else: - return self.form_invalid(form) - - return self.form_valid(form) diff --git a/InvenTree/templates/InvenTree/settings/currencies.html b/InvenTree/templates/InvenTree/settings/currencies.html index dd47bc6cdd..78598236f9 100644 --- a/InvenTree/templates/InvenTree/settings/currencies.html +++ b/InvenTree/templates/InvenTree/settings/currencies.html @@ -13,40 +13,43 @@ {% block settings %} - {% include "InvenTree/settings/header.html" %} - {% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %} - {% include "InvenTree/settings/setting.html" with key="CUSTOM_EXCHANGE_RATES" icon="fa-edit" %} + + + + + + + + {% for rate in rates %} + + + + + {% endfor %} + + + +
    {% trans "Base Currency" %}{{ base_currency }}
    {% trans "Exchange Rates" %}
    {{ rate.currency }}{{ rate.value }}
    + {% trans "Last Update" %} + + {% if rates_updated %} + {{ rates_updated }} + {% else %} + {% trans "Never" %} + {% endif %} +
    +
    + {% csrf_token %} + +
    +
    +
    -
    -
    -

    {% blocktrans with cur=default_currency %}Exchange Rates - Convert to {{cur}}{% endblocktrans %}

    -
    -
    - -
    -
    - {% csrf_token %} - {% load crispy_forms_tags %} - {% crispy form %} - {% if custom_rates is False %} - - {% else %} - - {% endif %} -
    -
    - {% endblock %} {% block js_ready %} {{ block.super }} - -{% if api_rates_success is False %} - var alert_msg = {% blocktrans %}"Failed to refresh exchange rates" {% endblocktrans %}; - showAlertOrCache("alert-danger", alert_msg, null, 5000); -{% endif %} - {% endblock %} \ No newline at end of file From 4520bb74478258b0842bb2af69658cbb99d6884b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 27 May 2021 16:36:26 +1000 Subject: [PATCH 235/300] PEP style fixes --- InvenTree/InvenTree/exchange.py | 2 +- InvenTree/InvenTree/views.py | 3 +-- InvenTree/common/models.py | 1 - InvenTree/common/test_views.py | 11 +++-------- InvenTree/company/tests.py | 13 ------------- 5 files changed, 5 insertions(+), 25 deletions(-) diff --git a/InvenTree/InvenTree/exchange.py b/InvenTree/InvenTree/exchange.py index dfbfff872c..0695e69f48 100644 --- a/InvenTree/InvenTree/exchange.py +++ b/InvenTree/InvenTree/exchange.py @@ -7,7 +7,7 @@ class InvenTreeExchange(SimpleExchangeBackend): """ Backend for automatically updating currency exchange rates. - Uses the exchangerate.host service API + Uses the exchangerate.host service API """ name = "InvenTreeExchange" diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 4189def492..4ac90bd722 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -26,7 +26,6 @@ from part.models import Part, PartCategory from stock.models import StockLocation, StockItem from common.models import InvenTreeSetting, ColorTheme from users.models import check_user_role, RuleSet -from InvenTree.helpers import clean_decimal import InvenTree.tasks @@ -775,7 +774,6 @@ class SettingsView(TemplateView): return ctx - class CurrencyRefreshView(RedirectView): url = reverse_lazy("settings-currencies") @@ -819,6 +817,7 @@ class CurrencySettingsView(TemplateView): return ctx + class AppearanceSelectView(FormView): """ View for selecting a color theme """ diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 6cfe5915e0..236e48770f 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -14,7 +14,6 @@ from django.db import models, transaction from django.db.utils import IntegrityError, OperationalError from django.conf import settings -import djmoney.settings from djmoney.models.fields import MoneyField from djmoney.contrib.exchange.models import convert_money from djmoney.contrib.exchange.exceptions import MissingRate diff --git a/InvenTree/common/test_views.py b/InvenTree/common/test_views.py index 8dc5830108..56a244ba0c 100644 --- a/InvenTree/common/test_views.py +++ b/InvenTree/common/test_views.py @@ -98,20 +98,15 @@ class SettingsViewTest(TestCase): Tests for a setting which has choices """ - setting = InvenTreeSetting.get_setting_object('INVENTREE_DEFAULT_CURRENCY') + setting = InvenTreeSetting.get_setting_object('PURCHASEORDER_REFERENCE_PREFIX') # Default value! - self.assertEqual(setting.value, 'USD') + self.assertEqual(setting.value, 'PO') url = self.get_url(setting.pk) # Try posting an invalid currency option - data, errors = self.post(url, {'value': 'XPQaaa'}, valid=False) - - self.assertIsNotNone(errors.get('value'), None) - - # Try posting a valid currency option - data, errors = self.post(url, {'value': 'AUD'}, valid=True) + data, errors = self.post(url, {'value': 'Purchase Order'}, valid=True) def test_binary_values(self): """ diff --git a/InvenTree/company/tests.py b/InvenTree/company/tests.py index 2c6e722440..b1e05efe14 100644 --- a/InvenTree/company/tests.py +++ b/InvenTree/company/tests.py @@ -11,9 +11,6 @@ from .models import Company, Contact, ManufacturerPart, SupplierPart from .models import rename_company_image from part.models import Part -from InvenTree.exchange import InvenTreeManualExchangeBackend -from djmoney.contrib.exchange.models import Rate - class CompanySimpleTest(TestCase): @@ -40,16 +37,6 @@ class CompanySimpleTest(TestCase): self.acme0002 = SupplierPart.objects.get(SKU='ACME0002') self.zerglphs = SupplierPart.objects.get(SKU='ZERGLPHS') self.zergm312 = SupplierPart.objects.get(SKU='ZERGM312') - - # Exchange rate backend - backend = InvenTreeManualExchangeBackend() - backend.update_rates(base_currency=backend.base_currency) - - Rate.objects.create( - currency='AUD', - value='1.35', - backend_id=backend.name, - ) def test_company_model(self): c = Company.objects.get(name='ABC Co.') From c71f4ed04577ac5450be7993e322db74bf054c89 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 27 May 2021 16:48:13 +1000 Subject: [PATCH 236/300] Add currency exchange unit tests --- InvenTree/InvenTree/tests.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index d65829cf8e..b7e5b98c1b 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -5,6 +5,12 @@ from django.test import TestCase import django.core.exceptions as django_exceptions from django.core.exceptions import ValidationError +from django.conf import settings + +from djmoney.money import Money +from djmoney.contrib.exchange.models import Rate, convert_money +from djmoney.contrib.exchange.exceptions import MissingRate + from .validators import validate_overage, validate_part_name from . import helpers from . import version @@ -13,6 +19,8 @@ from mptt.exceptions import InvalidMove from decimal import Decimal +import InvenTree.tasks + from stock.models import StockLocation @@ -308,3 +316,46 @@ class TestVersionNumber(TestCase): self.assertTrue(v_c > v_b) self.assertTrue(v_d > v_c) self.assertTrue(v_d > v_a) + + +class CurrencyTests(TestCase): + """ + Unit tests for currency / exchange rate functionality + """ + + def test_rates(self): + + # Initially, there will not be any exchange rate information + rates = Rate.objects.all() + + self.assertEqual(rates.count(), 0) + + # Without rate information, we cannot convert anything... + with self.assertRaises(MissingRate): + convert_money(Money(100, 'USD'), 'AUD') + + with self.assertRaises(MissingRate): + convert_money(Money(100, 'AUD'), 'USD') + + currencies = settings.CURRENCIES + + InvenTree.tasks.update_exchange_rates() + + rates = Rate.objects.all() + + self.assertEqual(rates.count(), len(currencies)) + + # Now that we have some exchange rate information, we can perform conversions + + # Forwards + convert_money(Money(100, 'USD'), 'AUD') + + # Backwards + convert_money(Money(100, 'AUD'), 'USD') + + # Convert between non base currencies + convert_money(Money(100, 'CAD'), 'NZD') + + # Convert to a symbol which is not covered + with self.assertRaises(MissingRate): + convert_money(Money(100, 'GBP'), 'ZWL') From 52fc698b51c8b87a02cecb5c1cf613786cf31e03 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 12:07:53 +1000 Subject: [PATCH 237/300] Remove debug message --- InvenTree/InvenTree/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 4ac90bd722..108908c571 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -775,6 +775,9 @@ class SettingsView(TemplateView): class CurrencyRefreshView(RedirectView): + """ + POST endpoint to refresh / update exchange rates + """ url = reverse_lazy("settings-currencies") @@ -783,8 +786,6 @@ class CurrencyRefreshView(RedirectView): On a POST request we will attempt to refresh the exchange rates """ - print("POST!") - # Will block for a little bit InvenTree.tasks.update_exchange_rates() From 4ddeab3330fa2af12254a56d02aa17c79cac929a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 12:44:39 +1000 Subject: [PATCH 238/300] Update exchange rates when launching the server - Ensures that the exchange rates don't get messed up if the base currency is changed! --- InvenTree/InvenTree/apps.py | 48 ++++++++++++++++++++++++++++++++++++ InvenTree/InvenTree/tasks.py | 4 +++ 2 files changed, 52 insertions(+) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index aa60058dcf..465dc2087b 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -4,6 +4,7 @@ import logging from django.apps import AppConfig from django.core.exceptions import AppRegistryNotReady +from django.conf import settings from InvenTree.ready import canAppAccessDatabase import InvenTree.tasks @@ -19,6 +20,7 @@ class InvenTreeConfig(AppConfig): if canAppAccessDatabase(): self.start_background_tasks() + self.update_exchange_rates() def start_background_tasks(self): @@ -49,3 +51,49 @@ class InvenTreeConfig(AppConfig): 'InvenTree.tasks.update_exchange_rates', schedule_type=Schedule.DAILY, ) + + def update_exchange_rates(self): + """ + Update exchange rates each time the server is started, *if*: + + a) Have not been updated recently (one day or less) + b) The base exchange rate has been altered + """ + + try: + from djmoney.contrib.exchange.models import ExchangeBackend + from datetime import datetime, timedelta + from InvenTree.tasks import update_exchange_rates + except AppRegistryNotReady: + pass + + base_currency = settings.BASE_CURRENCY + + update = False + + try: + backend = ExchangeBackend.objects.get(name='InvenTreeExchange') + + last_update = backend.last_update + + if last_update is not None: + delta = datetime.now().date() - last_update.date() + if delta > timedelta(days=1): + print(f"Last update was {last_update}") + update = True + else: + # Never been updated + print("Exchange backend has never been updated") + update = True + + # Backend currency has changed? + if not base_currency == backend.base_currency: + print(f"Base currency changed from {backend.base_currency} to {base_currency}") + update = True + + except (ExchangeBackend.DoesNotExist): + print("Exchange backend not found - updating") + update = True + + if update: + update_exchange_rates() diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 9a71d5d84c..92c58c24a8 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -168,6 +168,7 @@ def update_exchange_rates(): try: from InvenTree.exchange import InvenTreeExchange + from djmoney.contrib.exchange.models import Rate from django.conf import settings except AppRegistryNotReady: # Apps not yet loaded! @@ -182,6 +183,9 @@ def update_exchange_rates(): backend.update_rates(base_currency=base) + # Remove any exchange rates which are not in the provided currencies + Rate.objects.filter(backend="InvenTreeExchange").exclude(currency__in=settings.CURRENCIES).delete() + def send_email(subject, body, recipients, from_email=None): """ From 09782353703f6866d26573b5eade9821c7f49ae1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 12:49:50 +1000 Subject: [PATCH 239/300] Fix? --- InvenTree/InvenTree/tasks.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 92c58c24a8..994a344cc9 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -173,6 +173,9 @@ def update_exchange_rates(): except AppRegistryNotReady: # Apps not yet loaded! return + except: + # Other error? + return backend = InvenTreeExchange() print(f"Updating exchange rates from {backend.url}") From 7832ccccc298911dcabe37e823c67491df9bc052 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 12:54:55 +1000 Subject: [PATCH 240/300] Check if database tables are ready --- InvenTree/InvenTree/tasks.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py index 994a344cc9..d45df99152 100644 --- a/InvenTree/InvenTree/tasks.py +++ b/InvenTree/InvenTree/tasks.py @@ -168,7 +168,7 @@ def update_exchange_rates(): try: from InvenTree.exchange import InvenTreeExchange - from djmoney.contrib.exchange.models import Rate + from djmoney.contrib.exchange.models import ExchangeBackend, Rate from django.conf import settings except AppRegistryNotReady: # Apps not yet loaded! @@ -177,6 +177,16 @@ def update_exchange_rates(): # Other error? return + # Test to see if the database is ready yet + try: + backend = ExchangeBackend.objects.get(name='InvenTreeExchange') + except ExchangeBackend.DoesNotExist: + pass + except: + # Some other error + print("Database not ready") + return + backend = InvenTreeExchange() print(f"Updating exchange rates from {backend.url}") From be6e2aa2769c1d21f30c7b1e9efc5da671380f36 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 13:02:34 +1000 Subject: [PATCH 241/300] Better exception handling --- InvenTree/InvenTree/apps.py | 10 ++++++++-- InvenTree/InvenTree/ready.py | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/apps.py b/InvenTree/InvenTree/apps.py index 465dc2087b..aeddb714a0 100644 --- a/InvenTree/InvenTree/apps.py +++ b/InvenTree/InvenTree/apps.py @@ -6,7 +6,7 @@ from django.apps import AppConfig from django.core.exceptions import AppRegistryNotReady from django.conf import settings -from InvenTree.ready import canAppAccessDatabase +from InvenTree.ready import isInTestMode, canAppAccessDatabase import InvenTree.tasks @@ -20,7 +20,9 @@ class InvenTreeConfig(AppConfig): if canAppAccessDatabase(): self.start_background_tasks() - self.update_exchange_rates() + + if not isInTestMode(): + self.update_exchange_rates() def start_background_tasks(self): @@ -95,5 +97,9 @@ class InvenTreeConfig(AppConfig): print("Exchange backend not found - updating") update = True + except: + # Some other error - potentially the tables are not ready yet + return + if update: update_exchange_rates() diff --git a/InvenTree/InvenTree/ready.py b/InvenTree/InvenTree/ready.py index aa31fac947..5a4f1e9576 100644 --- a/InvenTree/InvenTree/ready.py +++ b/InvenTree/InvenTree/ready.py @@ -1,6 +1,17 @@ import sys +def isInTestMode(): + """ + Returns True if the database is in testing mode + """ + + if 'test' in sys.argv: + return True + + return False + + def canAppAccessDatabase(): """ Returns True if the apps.py file can access database records. From b7163124385044508e89fa4fd078f8fabeaa8f99 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 May 2021 13:24:18 +1000 Subject: [PATCH 242/300] Ignore actions for l10 branches --- .github/workflows/coverage.yaml | 9 ++++++++- .github/workflows/mysql.yaml | 9 ++++++++- .github/workflows/postgresql.yaml | 9 ++++++++- .github/workflows/style.yaml | 9 ++++++++- .github/workflows/translations.yml | 1 - 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index ad5f7a841e..6d0334b804 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -2,7 +2,14 @@ name: SQLite -on: ["push", "pull_request"] +on: + push: + branches-ignore: + - l10* + + pull_request: + branches-ignore: + - l10* jobs: diff --git a/.github/workflows/mysql.yaml b/.github/workflows/mysql.yaml index 5bafe56253..f0eb0efd7f 100644 --- a/.github/workflows/mysql.yaml +++ b/.github/workflows/mysql.yaml @@ -2,7 +2,14 @@ name: MySQL -on: ["push", "pull_request"] +on: + push: + branches-ignore: + - l10* + + pull_request: + branches-ignore: + - l10* jobs: diff --git a/.github/workflows/postgresql.yaml b/.github/workflows/postgresql.yaml index 3481895d85..9a56382c4e 100644 --- a/.github/workflows/postgresql.yaml +++ b/.github/workflows/postgresql.yaml @@ -2,7 +2,14 @@ name: PostgreSQL -on: ["push", "pull_request"] +on: + push: + branches-ignore: + - l10* + + pull_request: + branches-ignore: + - l10* jobs: diff --git a/.github/workflows/style.yaml b/.github/workflows/style.yaml index 31da3ec61a..df52de1dcb 100644 --- a/.github/workflows/style.yaml +++ b/.github/workflows/style.yaml @@ -1,6 +1,13 @@ name: Style Checks -on: ["push", "pull_request"] +on: + push: + branches-ignore: + - l10* + + pull_request: + branches-ignore: + - l10* jobs: style: diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index a3950b2002..24106c028e 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -5,7 +5,6 @@ on: branches: - master - jobs: build: From 0995ccee672835363aeadfff0a11db2b850ae372 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 29 May 2021 17:33:07 +1000 Subject: [PATCH 243/300] L10 merge master (#1617) * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * Adds a commit message * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * updated translation base * New Crowdin updates (#1551) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * New Crowdin updates (#1552) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * New Crowdin updates (#1568) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * New Crowdin updates (#1570) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * Trans merge fix (#1599) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * New Crowdin updates (#1597) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * updated translation base * Update github actions * L10 merge fix (#1614) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Update github actions (cherry picked from commit d9bbebddb0629af5690ad5a9ea408fafb8904335) * New Crowdin updates (#1603) * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Fix: New translations django.po from Crowdin * Update github actions (cherry picked from commit d9bbebddb0629af5690ad5a9ea408fafb8904335) * updated translation base Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- InvenTree/locale/de/LC_MESSAGES/django.po | 1189 +++++++++++---------- InvenTree/locale/en/LC_MESSAGES/django.po | 1147 +++++++++++--------- InvenTree/locale/es/LC_MESSAGES/django.po | 1158 +++++++++++--------- InvenTree/locale/fr/LC_MESSAGES/django.po | 1156 +++++++++++--------- InvenTree/locale/it/LC_MESSAGES/django.po | 1156 +++++++++++--------- InvenTree/locale/ja/LC_MESSAGES/django.po | 1156 +++++++++++--------- InvenTree/locale/pl/LC_MESSAGES/django.po | 1169 +++++++++++--------- InvenTree/locale/ru/LC_MESSAGES/django.po | 1156 +++++++++++--------- InvenTree/locale/tr/LC_MESSAGES/django.po | 1156 +++++++++++--------- InvenTree/locale/zh/LC_MESSAGES/django.po | 1156 +++++++++++--------- 10 files changed, 6274 insertions(+), 5325 deletions(-) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 300a639a69..7fdc9f1943 100644 --- a/InvenTree/locale/de/LC_MESSAGES/django.po +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: German\n" "Language: de_DE\n" @@ -33,42 +33,42 @@ msgstr "Keine passende Aktion gefunden" msgid "Enter date" msgstr "Datum eingeben" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "Bestätigen" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "Löschung bestätigen" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "Löschung von Position bestätigen" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "Passwort eingeben" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "Neues Passwort eingeben" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "Passwort wiederholen" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "Neues Passwort bestätigen" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "Thema anwenden" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "Kategorie auswählen" @@ -122,9 +122,9 @@ msgstr "Kommentar" msgid "File comment" msgstr "Datei-Kommentar" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "Benutzer" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "Hochladedatum" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "Beschreibung (optional)" msgid "parent" msgstr "Eltern" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "Englisch" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "Französisch" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "Deutsch" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "Polnisch" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "Türkisch" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "Zurückgegeben" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "Versendet" @@ -372,27 +372,27 @@ msgstr "Überschuss darf 100% nicht überschreiten" msgid "Overage must be an integer value or a percentage" msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "Element löschen" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "Häkchen setzen um Löschung von Objekt zu bestätigen" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "Benutzerinformationen bearbeiten" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "Passwort eingeben" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "Passwörter stimmen nicht überein" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "Systeminformationen" @@ -444,10 +444,10 @@ msgstr "Bauauftrags-Referenz" msgid "Order target date" msgstr "geplantes Bestelldatum" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "Zieldatum für Bauauftrag-Fertigstellung." #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "Zieldatum für Bauauftrag-Fertigstellung." #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "Anzahl" @@ -528,11 +530,11 @@ msgstr "Bauauftrag als vollständig markieren" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "Lagerort" @@ -540,14 +542,14 @@ msgstr "Lagerort" msgid "Location of completed parts" msgstr "Lagerort der Endprodukte" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "Status" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "Menge der BestandsObjekte für Zuordnung auswählen" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "Bauauftrag" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "Bauaufträge" @@ -602,7 +604,7 @@ msgstr "Bauauftragsreferenz" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "Referenz" msgid "Brief description of the build" msgstr "Kurze Beschreibung des Baus" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "Eltern-Bauauftrag" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "Bauauftrag, zu dem dieser Bauauftrag zugwiesen ist" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "Bauauftrag, zu dem dieser Bauauftrag zugwiesen ist" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "Teil" @@ -691,7 +693,7 @@ msgstr "Fertiggestellte Teile" msgid "Number of stock items which have been completed" msgstr "Anzahl der fertigen BestandsObjekte" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "Bauauftrags-Status" @@ -732,10 +734,10 @@ msgstr "Aufgegeben von" msgid "User who issued this build order" msgstr "Nutzer der diesen Bauauftrag erstellt hat" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "Verantwortlicher Benutzer" @@ -749,8 +751,8 @@ msgstr "Nutzer der für diesen Bauauftrag zuständig ist" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "Externer Link" @@ -768,12 +770,12 @@ msgstr "Link zu einer externen URL" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "Notizen" @@ -823,7 +825,7 @@ msgstr "Reserviermenge muss größer null sein" msgid "Quantity must be 1 for serialized stock" msgstr "Anzahl muss 1 für Objekte mit Seriennummer sein" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "Bauauftrag starten um Teile zuzuweisen" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "BestandsObjekt" @@ -913,7 +915,7 @@ msgstr "Dieser Bauauftrag hat keine zugeordneten Stücklisten-Einträge" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "Seriennummer" @@ -921,8 +923,8 @@ msgstr "Seriennummer" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "Anhänge" @@ -943,119 +945,119 @@ msgstr "Keine BestandsObjekte gefunden, die diesem Endprodukt automatisch zugewi msgid "Stock items will have to be manually allocated" msgstr "BestandsObjekte müssen manuell zugewiesen werden" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "Dieser Bauauftrag ist dem Auftrag %(link)s zugeordnet" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "Dieser Bauauftrag ist dem Bauauftrag %(link)s untergeordnet" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "Bauauftrag ist bereit abgeschlossen zu werden" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "Bauauftrag kann nicht abgeschlossen werden, da es noch ausstehende Endprodukte gibt" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "Benötigte Teil-Anzahl wurde noch nicht fertiggestellt" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "Lagerbestand wurde Bauauftrag noch nicht vollständig zugewiesen" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "Admin" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "Überfällig" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "Aktionen drucken" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "Bauauftrag drucken" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "Bauauftrag fertigstellen" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "Bau-Auftrag Aktionen" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "Bauauftrag bearbeiten" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "Bauauftrag abbrechen" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "Bau-Status" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "Bauauftrag war fällig am %(target)s" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "Fortschritt" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "Auftrag" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "Aufgegeben von" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "Unfertige Endprodukte" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "Bauauftrag kann nicht abgeschlossen werden, da es noch unvollständige Endprodukte gibt" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "Ziel-Lagerort nicht angegeben" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "Losnummer" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "Erstellt" @@ -1282,8 +1284,8 @@ msgstr "Bermerkungen bearbeiten" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "Speichern" @@ -1429,7 +1431,7 @@ msgstr "Bauobjekt aktualisiert" msgid "Add Build Order Attachment" msgstr "Bauauftrags-Anhang hinzufügen" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "Anhang hinzugefügt" @@ -1466,368 +1468,360 @@ msgstr "Fehler beim Lesen der Datei (falsche Größe)" msgid "Error reading file (data could be corrupted)" msgstr "Fehler beim Lesen der Datei (Daten könnten beschädigt sein)" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "Datei" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "Datei zum Hochladen auswählen" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "{name.title()} Datei" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "{name} Datei zum Hochladen auswählen" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "InvenTree Instanzname" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "Kurze Beschreibung der Instanz" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "Name der Instanz verwenden" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "Den Namen der Instanz in der Titelleiste verwenden" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "Firmenname" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "interner Firmenname" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "Basis-URL" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "Basis-URL für dieses Instanz" -#: common/models.py:84 -msgid "Default Currency" -msgstr "Standard-Währung" - #: common/models.py:85 -msgid "Default currency" -msgstr "Standard-Währung" - -#: common/models.py:91 msgid "Download from URL" msgstr "Von URL herunterladen" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "Herunterladen von externen Bildern und Dateien von URLs erlaubt" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "Bacode-Feature verwenden" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "Barcode-Scanner Unterstützung" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "IPN Regex" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "RegEx Muster für die Zuordnung von Teil-IPN" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "Mehrere Artikel mit gleicher IPN erlaubt" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "Mehrere Artikel mit gleicher IPN erlaubt" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "Ändern von IPN erlaubt" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "Ändern der IPN während des Bearbeiten eines Teils erlaubt" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "Teil-Stückliste kopieren" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "Stückliste von Teil kopieren wenn das Teil dupliziert wird " -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "Teil-Parameter kopieren" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "Parameter-Daten für dieses Teil kopieren wenn das Teil dupliziert wird" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "Teil-Testdaten kopieren" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "Test-Daten für dieses Teil kopieren wenn das Teil dupliziert wird" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "Kategorie-Parametervorlage kopieren" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "Kategorie-Parameter Vorlagen kopieren wenn ein Teil angelegt wird" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "Aktuelle Teile-Stände" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "Anzahl der neusten Teile auf der Startseite" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "Vorlage" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "Teile sind standardmäßig Vorlagen" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "Baugruppe" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "Teile können standardmäßig aus anderen Teilen angefertigt werden" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "Komponente" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "Teile können standardmäßig in Baugruppen benutzt werden" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "Kaufbar" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "Artikel sind grundsätzlich kaufbar" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "Verkäuflich" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "Artikel sind grundsätzlich verkaufbar" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "Nachverfolgbar" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "Artikel sind grundsätzlich verfolgbar" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "Virtuell" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "Teile sind grundsätzlich virtuell" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "zeige Bestand in Eingabemasken" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "Zeige den verfügbaren Bestand in einigen Eingabemasken" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "Entwickler-Modus" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "Berichte im Entwickler-Modus generieren (als HTML)" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "Seitengröße" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "Standardseitenformat für PDF-Bericht" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "Test-Berichte" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "Erstellung von Test-Berichten aktivieren" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "Bestands-Ablauf" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "Ablaufen von Bestand ermöglichen" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "Abgelaufenen Bestand verkaufen" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "Verkauf von abgelaufenem Bestand erlaubt" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "Bestands-Stehzeit" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "Anzahl an Tagen, an denen Bestand als abgestanden markiert wird, bevor sie ablaufen" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "Tage" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "Abgelaufenen Bestand verbauen" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "Verbauen von abgelaufenen Bestand erlaubt" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "Bestands-Eigentümerkontrolle" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "Eigentümerkontrolle für Lagerorte und Teile aktivieren" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "Gruppieren nach Teil" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "Bestand in Tabellen anhand von Teil-Referenz gruppieren" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "aktueller Bestand" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "Anzahl des geänderten Bestands auf der Startseite" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "Bauauftrag-Referenz Präfix" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "Präfix für Bauauftrag-Referenz" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "Bauauftrag-Referenz RegEx" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "RegEx Muster für die Zuordnung von Bauauftrag-Referenzen" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "Auftrags-Referenz Präfix" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "Präfix für Auftrags-Referenz" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "Bestellungs-Referenz Präfix" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "Präfix für Bestellungs-Referenz" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "Einstellungs-Schlüssel (muss einzigartig sein, Groß-/ Kleinschreibung wird nicht beachtet)" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "Einstellungs-Wert" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "Nur Ganzzahl eingeben" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "Wahrheitswert erforderlich" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "Nur Ganzzahl eingeben" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "Schlüsseltext muss eindeutig sein" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "Preisstaffelungs Anzahl" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "Preis" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "Stückpreis für die angegebene Anzahl" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "Standard" @@ -1882,7 +1876,7 @@ msgstr "URL" msgid "Image URL" msgstr "Bild-URL" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "Einzelpreis" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "Produziert diese Firma Teile?" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "Basisteil" @@ -2011,7 +2005,7 @@ msgstr "Teil auswählen" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "Teilbeschreibung des Herstellers" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "Lagerbestandseinheit (SKU) des Zulieferers" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "Herstellerteil" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "Zuliefererbeschreibung des Teils" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "Mindestpreis" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "Verpackungen" @@ -2154,9 +2148,11 @@ msgstr "Sind Sie sicher, dass Sie die Firma '%(name)s' löschen wollen?" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." -msgstr "Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
    \n" +msgstr "" +"Es gibt %(count)s Teile, die von diesem Unternehmen bezogen werden.
    \n" "Wenn dieser Lieferant gelöscht wird, werden auch diese Zulieferer-Teile gelöscht." #: company/templates/company/detail.html:21 @@ -2172,10 +2168,10 @@ msgid "Uses default currency" msgstr "verwendet Standard-Währung" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "Kunde" @@ -2221,7 +2217,7 @@ msgstr "Teile löschen" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "Neues Teil" @@ -2268,7 +2264,7 @@ msgstr "Neues Zuliefererteil anlegen" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "Neues Zuliefererteil" @@ -2291,7 +2287,7 @@ msgstr "Zulieferer-Liste" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "Teil bestellen" @@ -2325,8 +2321,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "Für dieses Herstellerteil sind %(count)s Lieferanten definiert. Wenn Sie es löschen, werden die folgenden Lieferantenteile ebenfalls gelöscht:" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "Zulieferer" @@ -2343,7 +2339,7 @@ msgstr "Herstellerteil-Bestand" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "Lagerbestand" @@ -2401,10 +2397,10 @@ msgstr "Teilbestand" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "Aufträge" @@ -2413,10 +2409,10 @@ msgstr "Aufträge" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "Bestellungen" @@ -2447,7 +2443,7 @@ msgstr "Neuer Auftrag" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "Zuliefererteil" @@ -2496,7 +2492,7 @@ msgid "Pricing Information" msgstr "Preisinformationen ansehen" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "Preisstaffel hinzufügen" @@ -2515,8 +2511,8 @@ msgstr "Preisstaffel bearbeiten" msgid "Delete price break" msgstr "Preisstaffel löschen" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "Hersteller" @@ -2538,20 +2534,20 @@ msgstr "Firmen" msgid "New Company" msgstr "Neue Firma" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "Bild herunterladen" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "Bildgröße überschreitet maximal-erlaubte Größe für Downloads" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "Ungültige Antwort {code}" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "Angegebene URL ist kein gültiges Bild" @@ -2603,7 +2599,7 @@ msgstr "Herstellerteil löschen" msgid "Edit Supplier Part" msgstr "Zuliefererteil bearbeiten" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "Neues Zuliefererteil anlegen" @@ -2611,15 +2607,15 @@ msgstr "Neues Zuliefererteil anlegen" msgid "Delete Supplier Part" msgstr "Zuliefererteil entfernen" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "neue Preisstaffel hinzufügt" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "Preisstaffel bearbeiten" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "Preisstaffel löschen" @@ -2693,11 +2689,11 @@ msgid "Mark order as complete" msgstr "Bestellung als vollständig markieren" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "Bestellung stornieren" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "Bestellung versenden" @@ -2794,7 +2790,7 @@ msgstr "Geplantes Lieferdatum für Auftrag." msgid "Date order was completed" msgstr "Datum an dem der Auftrag fertigstellt wurde" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -2860,8 +2856,8 @@ msgstr "Bestellung" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "Bestellung" @@ -2872,7 +2868,7 @@ msgstr "Zuliefererteil" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "Empfangen" @@ -2881,7 +2877,7 @@ msgid "Number of items received" msgstr "Empfangene Objekt-Anzahl" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "Preis" @@ -2889,8 +2885,9 @@ msgstr "Preis" msgid "Unit purchase price" msgstr "Preis pro Einheit" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "Verkaufspreis" @@ -2941,12 +2938,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "Sind Sie sicher, dass Sie diesen Anhang löschen wollen?" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "Drucken" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "Bestellung bearbeiten" @@ -2964,12 +2961,12 @@ msgid "Purchase Order Details" msgstr "Bestellungs-Details" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "Bestellreferenz" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "Bestellstatus" @@ -2982,7 +2979,7 @@ msgstr "Aufgegeben" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "Neuer Lagerort" @@ -3194,14 +3191,14 @@ msgstr "Berichte drucken" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "Ausstehende Teile für %(order)s - %(desc)s empfangen" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3216,7 +3213,7 @@ msgid "Order Code" msgstr "Bestellnummer" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "Bestellt" @@ -3232,20 +3229,20 @@ msgstr "Fehler: verknüpftes Teil wurde gelöscht" msgid "Remove line" msgstr "Position entfernen" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "Dieser Auftrag ist nicht vollständig zugeordnet" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "Packliste" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "Auftragsdetails" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "Kundenreferenz" @@ -3264,7 +3261,7 @@ msgstr "Abbruch dieser Bestellung bedeutet, dass sie nicht länger bearbeitbar i msgid "Sales Order Items" msgstr "Auftrags-Positionen" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "Aktionen" @@ -3559,7 +3556,7 @@ msgstr "{part} Stückpreis auf {price} und Menge auf {qty} aktualisiert" msgid "Default Location" msgstr "Standard-Lagerort" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "Verfügbarer Lagerbestand" @@ -3632,7 +3629,7 @@ msgstr "Zulieferer einschließen" msgid "Include part supplier data in exported BOM" msgstr "Zulieferer-Daten in Stückliste-Export einschließen" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "Ausgangsteil" @@ -3708,7 +3705,7 @@ msgstr "Parameter-Vorlage zu Kategorien dieser Ebene hinzufügen" msgid "Add parameter template to all categories" msgstr "Parameter-Vorlage zu allen Kategorien hinzufügen" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "Untergeordnetes Teil" @@ -3728,7 +3725,7 @@ msgstr "Standard Stichwörter" msgid "Default keywords for parts in this category" msgstr "Standard-Stichworte für Teile dieser Kategorie" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "Teil-Kategorie" @@ -3798,7 +3795,7 @@ msgstr "Schlüsselwörter" msgid "Part keywords to improve visibility in search results" msgstr "Schlüsselworte um die Sichtbarkeit in Suchergebnissen zu verbessern" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "Kategorie" @@ -3808,7 +3805,7 @@ msgid "Part category" msgstr "Teile-Kategorie" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "IPN (Interne Produktnummer)" @@ -3853,7 +3850,7 @@ msgstr "Minimaler Lagerbestand" msgid "Minimum allowed stock level" msgstr "Minimal zulässiger Lagerbestand" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "Einheiten" @@ -3924,167 +3921,167 @@ msgstr "Erstellungs-Nutzer" msgid "Sell multiple" msgstr "Mehrere verkaufen" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "Test-Vorlagen können nur für verfolgbare Teile angelegt werden" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "Ein Test mit diesem Namen besteht bereits für dieses Teil" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "Test-Name" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "Namen für diesen Test eingeben" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "Test-Beschreibung" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "Beschreibung für diesen Test eingeben" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "Benötigt" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "Muss dieser Test erfolgreich sein?" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "Erfordert Wert" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "Muss für diesen Test ein Wert für das Test-Ergebnis eingetragen werden?" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "Anhang muss eingegeben werden" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "Muss für diesen Test ein Anhang für das Test-Ergebnis hinzugefügt werden?" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "Vorlagen-Name des Parameters muss eindeutig sein" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "Name des Parameters" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "Einheit des Parameters" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "Parameter Vorlage" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "Wert" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "Parameter Wert" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "Standard-Wert" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "Standard Parameter Wert" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "Ausgangsteil auswählen" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "Optional" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "Diese Stücklisten-Position ist optional" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "Überschuss" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "Referenz der Postion auf der Stückliste" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "Notizen zur Stücklisten-Position" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "Prüfsumme" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "Geerbt" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "Diese Stücklisten-Position wird in die Stücklisten von Teil-Varianten vererbt" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "Menge muss eine Ganzzahl sein" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "Zuliefererteil muss festgelegt sein" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "Stücklisten-Position" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "Teil 1" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "Teil 2" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "verknüpftes Teil auswählen" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "Fehler bei Verwandschaft: Ist das Teil mit sich selbst verwandt oder ist das die Verwandtschaft nicht eindeutig?" @@ -4152,7 +4149,7 @@ msgstr "Stückliste bearbeiten" msgid "Validate Bill of Materials" msgstr "Stückliste kontrollieren" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "Stückliste exportieren" @@ -4168,8 +4165,8 @@ msgstr "Ausgewählte Stücklistenpositionen löschen?" msgid "All selected BOM items will be deleted" msgstr "Alle ausgewählte Stücklistenpositionen werden gelöscht" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "Neues Teil anlegen" @@ -4250,7 +4247,7 @@ msgstr "Neuen Bauauftrag beginnen" msgid "All parts" msgstr "Alle Teile" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "Teil-Kategorie anlegen" @@ -4368,7 +4365,7 @@ msgstr "Parameter" msgid "Part Parameters" msgstr "Teilparameter" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "Teil duplizieren" @@ -4505,27 +4502,122 @@ msgstr "Zuweisungen" msgid "Used In" msgstr "Benutzt in" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +#, fuzzy +#| msgid "Sell Price Information" +msgid "Order Price Information" +msgstr "Verkaufspreis Informationen" + +#: part/templates/part/navbar.html:75 +#, fuzzy +#| msgid "Order Part" +msgid "Order Price" +msgstr "Teil bestellen" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "Preisinformationen ansehen" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "Teil Test-Vorlagen" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "Tests" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "Verknüpfte Teile" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "Teil-Bemerkungen" +#: part/templates/part/order_prices.html:21 +#, fuzzy +#| msgid "Pricing Information" +msgid "Pricing ranges" +msgstr "Preisinformationen ansehen" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "Zulieferer-Preise" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "Stückpreis" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "Gesamtkosten" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "Keine Zulieferer-Preise verfügbar" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "Stücklistenpreise" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "Anmerkung: Stücklistenbepreisung für dieses Teil ist unvollständig" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "Keine Stücklisten-Preise verfügbar" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "Keine Preise für dieses Teil verfügbar" + +#: part/templates/part/order_prices.html:113 +#, fuzzy +#| msgid "Part Pricing" +msgid "Stock Pricing" +msgstr "Teilbepreisung" + +#: part/templates/part/order_prices.html:121 +#, fuzzy +#| msgid "No pricing information is available for this part." +msgid "No stock pricing history is available for this part." +msgstr "Keine Preise für dieses Teil verfügbar" + +#: part/templates/part/order_prices.html:140 +#, fuzzy, python-format +#| msgid "Single Price" +msgid "Single Price - %(currency)s" +msgstr "Einzelpreis" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "Parameter hinzufügen" @@ -4559,126 +4651,94 @@ msgstr "Neue Teilparametervorlage anlegen" msgid "Part List" msgstr "Teileliste" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "Dieses Teil ist eine Variante von %(link)s" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "Inaktiv" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "Teil favorisieren" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "Barcode Aktionen" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "QR-Code anzeigen" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "Label drucken" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "Kosteninformationen ansehen" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "Lagerbestand zählen" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "Teile Aktionen" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "Teil duplizieren" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "Teil bearbeiten" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "Teil löschen" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "Dies ist ein virtuelles Teil" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "Dieses Teil ist eine Variante von %(link)s" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "Auf Lager" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "Für Bauaufträge benötigt" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "Benötigt für Aufträge" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "Zu Bauaufträgen zugeordnet" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "Herstellbar" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "Im Bau" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "Berechnen" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "Zulieferer-Preise" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "Stückpreis" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "Gesamtkosten" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "Keine Zulieferer-Preise verfügbar" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "Stücklistenpreise" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "Anmerkung: Stücklistenbepreisung für dieses Teil ist unvollständig" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "Keine Stücklisten-Preise verfügbar" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "Keine Preise für dieses Teil verfügbar" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "Test Vorlage hinzufügen" @@ -4788,212 +4848,212 @@ msgstr "neue Variante anlegen" msgid "Unknown database" msgstr "Unbekannte Datenbank" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "verknüpftes Teil hinzufügen" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "verknüpftes Teil entfernen" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "Teilanhang hinzufügen" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "Anhang bearbeiten" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "Teilanhang aktualisiert" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "Teilanhang löschen" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "Teilanhang gelöscht" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "Testvorlage anlegen" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "Testvorlage bearbeiten" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "Testvorlage löschen" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "Teil-Kategorie auswählen" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "Kategorie für {n} Teile setzen" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "Variante anlegen" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "Teil kopiert" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "Übereinstimmung gefunden - Teil trotzdem anlegen" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "Neues Teil angelegt" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "Teil-QR-Code" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "Teilbild hochladen" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "Teilbild aktualisiert" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "Teilbild auswählen" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "Teilbild nicht gefunden" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "Teileigenschaften bearbeiten" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "Stückliste duplizieren" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "bestätige Duplizierung Stückliste von übergeordneter Stückliste" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "Stückliste überprüfen" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "Bestätigen, dass Stückliste korrekt ist" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "überprüfte Stückliste" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "Keine Stückliste angegeben" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "Bitte eine gültige Anzahl eingeben" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "Bitte ein gültiges Teil auswählen" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "Teil doppelt ausgewählt" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "Teil auswählen" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "gewähltes Teil erzeugt rekursive Stückliste" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "Anzahl angeben" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "Löschen des Teils bestätigen" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "Teil wurde gelöscht" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "Teilbepreisung" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "Teilparametervorlage bearbeiten" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "Teilparametervorlage löschen" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "Teilparameter anlegen" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "Teilparameter bearbeiten" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "Teilparameter löschen" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "Teil-Kategorie bearbeiten" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "Teil-Kategorie löschen" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "Teil-Kategorie wurde gelöscht" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "Kategorieparametervorlage anlegen" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "Kategorieparametervorlage bearbeiten" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "Kategorieparametervorlage löschen" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "Stücklisten-Position anlegen" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "Stücklisten-Position bearbeiten" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "löschen von Stücklisten-Position bestätigen" @@ -5128,7 +5188,7 @@ msgid "Moved {n} parts to {loc}" msgstr "{n} Teile nach {loc} bewegt" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "Ablaufdatum" @@ -5278,7 +5338,7 @@ msgstr "Wo wird dieses Teil normalerweise gelagert?" msgid "Packaging this stock item is stored in" msgstr "Die Verpackung dieses BestandsObjekt ist gelagert in" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "verbaut in" @@ -5413,173 +5473,173 @@ msgstr "neuer Eintrag" msgid "Stock Item Attachments" msgstr "BestandsObjekt-Anhang" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "Sie gehören nicht zu den Eigentümern dieses Objekts und können es nicht ändern." - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "Dieses BestandsObjekt wird gerade hergestellt und kann nicht geändert werden." - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "Ändern des BestandsObjekts in der Bauauftrag-Ansicht." - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "Dieses BestandsObjekt hat nicht alle Tests bestanden" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "Dieses BestandsObjekt ist dem Auftrag %(link)s zugewiesen (Menge: %(qty)s)" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "Dieses BestandsObjekt ist dem Bauauftrag %(link)s zugewiesen (Menge: %(qty)s)" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "Dieses BestandsObjekt ist serialisiert. Es hat eine eindeutige Seriennummer und die Anzahl kann nicht angepasst werden." - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "Dieses BestandsObjekt kann nicht gelöscht werden, da es Kinder besitzt" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "Dieses BestandsObjekt wird automatisch gelöscht wenn der Lagerbestand aufgebraucht ist." - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "abgelaufen" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "überfällig" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "Barcode abhängen" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "Barcode anhängen" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "zu Lagerort einscannen" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "Druck Aktionen" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "Test-Bericht" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "Bestands-Anpassungs Aktionen" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "Bestand zählen" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "Bestand hinzufügen" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "Bestand entfernen" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "Lagerbestand serialisieren" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "Bestand verschieben" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "Kunden zuweisen" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "zu Bestand zurückgeben" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "BestandsObjekt deinstallieren" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "Deinstallieren" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "Bestands-Aktionen" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "in Variante ändern" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "BestandsObjekt duplizieren" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "BestandsObjekt bearbeiten" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "BestandsObjekt löschen" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "Sie gehören nicht zu den Eigentümern dieses Objekts und können es nicht ändern." + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "Dieses BestandsObjekt wird gerade hergestellt und kann nicht geändert werden." + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "Ändern des BestandsObjekts in der Bauauftrag-Ansicht." + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "Dieses BestandsObjekt hat nicht alle Tests bestanden" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "Dieses BestandsObjekt ist dem Auftrag %(link)s zugewiesen (Menge: %(qty)s)" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "Dieses BestandsObjekt ist dem Bauauftrag %(link)s zugewiesen (Menge: %(qty)s)" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "Dieses BestandsObjekt ist serialisiert. Es hat eine eindeutige Seriennummer und die Anzahl kann nicht angepasst werden." + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "Dieses BestandsObjekt kann nicht gelöscht werden, da es Kinder besitzt" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "Dieses BestandsObjekt wird automatisch gelöscht wenn der Lagerbestand aufgebraucht ist." + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "BestandsObjekt-Details" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "Kein Lagerort gesetzt" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "Barcode-Bezeichner" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "Elternposition" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "Dieses BestandsObjekt lief am %(item.expiry_date)s ab" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "Dieses BestandsObjekt läuft am %(item.expiry_date)s ab" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "Zuletzt aktualisiert" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "Letzte Inventur" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "Keine Inventur ausgeführt" @@ -5932,7 +5992,7 @@ msgstr "{n} BestandsObjekte gelöscht" #: stock/views.py:1222 msgid "Edit Stock Item Status" -msgstr "Lagerbestandsstatus bearbeiten" +msgstr "Status bearbeiten" #: stock/views.py:1245 msgid "Edit Stock Item" @@ -6068,11 +6128,13 @@ msgstr "Farbschemata" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " -msgstr "\n" +msgstr "" +"\n" "\t\tDie CSS Datei \"%(invalid_color_theme)s.css\" für das aktuell ausgewählte Farbschema wurde nicht gefunden.
    \n" "\t\tBitte ein anderes Farbschema auswählen:)\n" "\t " @@ -6111,11 +6173,35 @@ msgstr "Vorlage bearbeiten" msgid "Delete Template" msgstr "Vorlage löschen" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "Währungseinstellungen" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "Basiswährung" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "Wechselkurse" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "Letzte Aktualisierung" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "Nie" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "Jetzt aktualisieren" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "Systemweite InvenTree-Einstellungen" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "Barcode-Einstellungen" @@ -6194,10 +6280,14 @@ msgid "Global" msgstr "Systemweit" #: templates/InvenTree/settings/tabs.html:19 +msgid "Currencies" +msgstr "Währungen" + +#: templates/InvenTree/settings/tabs.html:22 msgid "Report" msgstr "Bericht" -#: templates/InvenTree/settings/tabs.html:22 +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "Kategorien" @@ -6243,46 +6333,50 @@ msgid "Update Available" msgstr "Aktualisierung verfügbar" #: templates/about.html:34 +msgid "API Version" +msgstr "API-Version" + +#: templates/about.html:39 msgid "Django Version" msgstr "Django-Version" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "Commit-Hash" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "Commit-Datum" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "InvenTree-Dokumentation" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "Code auf GitHub ansehen" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "Danksagung" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "Mobile App" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "Fehlerbericht senden" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "In die Zwischenablage kopieren" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "Versionsinformationen kopieren" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6412,41 +6506,49 @@ msgstr "Barcode entspricht keinem Lagerort" msgid "Open subassembly" msgstr "Unterbaugruppe öffnen" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "Keine Preisinformation verfügbar" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "ja" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "nein" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "Stückliste anzeigen" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "Stücklisten-Position kontrollieren" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "Diese Position wurde kontrolliert" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "Stücklisten-Position bearbeiten" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "Stücklisten-Position löschen" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "Keine Stücklisten-Position(en) gefunden" @@ -6489,7 +6591,7 @@ msgstr "Keine Bauaufträge passen zur Anfrage" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "Auswählen" @@ -6752,6 +6854,12 @@ msgstr "Testergebnis löschen" msgid "This test is defined for a parent part" msgstr "Dieses Testergebnis ist für ein Hauptteil" +#: templates/js/part.js:727 +#, fuzzy +#| msgid "Single Price" +msgid "Single Price Difference" +msgstr "Einzelpreis" + #: templates/js/report.js:47 msgid "items selected" msgstr "BestandsObjekt ausgewählt" @@ -6928,11 +7036,11 @@ msgstr "Inventur" #: templates/js/stock.js:825 msgid "Stock Status" -msgstr "Bestandsstatus" +msgstr "Status" #: templates/js/stock.js:840 msgid "Set Stock Status" -msgstr "Bestandsstatus setzen" +msgstr "Status setzen" #: templates/js/stock.js:854 msgid "Select Status Code" @@ -6946,55 +7054,55 @@ msgstr "Status Code muss ausgewählt werden" msgid "Invalid date" msgstr "Ungültiges Datum" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "Standort nicht mehr vorhanden" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "Bestellung existiert nicht mehr" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "Kunde existiert nicht mehr" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "Lagerbestand existiert nicht mehr" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "Hinzugefügt" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "Entfernt" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "Keine Benutzerinformation" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "Tracking-Eintrag bearbeiten" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "Tracking-Eintrag löschen" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "Neuen Lagerort anlegen" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "Seriennummer" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "Installiert" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "Installiere Objekt" @@ -7110,7 +7218,7 @@ msgstr "zeige zu Kunden zugeordnete Einträge" #: templates/js/table_filters.js:198 templates/js/table_filters.js:199 msgid "Stock status" -msgstr "Bestandsstatus" +msgstr "Status" #: templates/js/table_filters.js:232 msgid "Build status" @@ -7327,11 +7435,11 @@ msgstr "Server läuft im Debug-Modus" #: templates/stats.html:33 msgid "Docker Mode" -msgstr "" +msgstr "Docker-Modus" #: templates/stats.html:34 msgid "Server is deployed using docker" -msgstr "" +msgstr "Server wird mit Docker bereitgestellt" #: templates/stats.html:40 msgid "Server status" @@ -7403,7 +7511,7 @@ msgstr "Status ändern" #: templates/stock_table.html:60 msgid "Change stock status" -msgstr "Bestandsstatus ändern" +msgstr "Status ändern" #: templates/stock_table.html:63 msgid "Delete selected items" @@ -7476,4 +7584,3 @@ msgstr "Berechtigungen Einträge zu ändern" #: users/models.py:187 msgid "Permission to delete items" msgstr "Berechtigung Einträge zu löschen" - diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 7e057e4153..ffe58c6405 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -34,42 +34,42 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -123,9 +123,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "" @@ -134,7 +134,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -172,23 +172,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -233,7 +233,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -373,27 +373,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -445,10 +445,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -462,8 +462,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -474,20 +474,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -529,11 +531,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -541,14 +543,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -581,7 +583,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -593,7 +595,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -603,7 +605,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -614,7 +616,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -624,17 +626,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -644,7 +646,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -692,7 +694,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -733,10 +735,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -750,8 +752,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -769,12 +771,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -824,7 +826,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -839,10 +841,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -914,7 +916,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -922,8 +924,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -944,119 +946,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1192,15 +1194,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1283,8 +1285,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1430,7 +1432,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1467,368 +1469,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1883,7 +1877,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1999,7 +1993,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2012,7 +2006,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2031,7 +2025,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2055,7 +2049,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2072,7 +2066,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2087,7 +2081,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2173,10 +2167,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2222,7 +2216,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2269,7 +2263,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2292,7 +2286,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2326,8 +2320,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2344,7 +2338,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2402,10 +2396,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2414,10 +2408,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2448,7 +2442,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2497,7 +2491,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2516,8 +2510,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2539,20 +2533,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2604,7 +2598,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2612,15 +2606,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2694,11 +2688,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2795,7 +2789,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2861,8 +2855,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2873,7 +2867,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2882,7 +2876,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2890,8 +2884,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2942,12 +2937,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2965,12 +2960,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2983,7 +2978,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3195,14 +3190,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3217,7 +3212,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3233,20 +3228,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3265,7 +3260,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3560,7 +3555,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3633,7 +3628,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3709,7 +3704,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3729,7 +3724,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3799,7 +3794,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3809,7 +3804,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3854,7 +3849,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3925,167 +3920,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4153,7 +4148,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4169,8 +4164,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4251,7 +4246,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4369,7 +4364,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4506,27 +4501,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4560,126 +4639,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4789,212 +4836,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5129,7 +5176,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5279,7 +5326,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5414,173 +5461,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6110,11 +6157,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6193,10 +6264,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6242,46 +6317,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6411,41 +6490,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6488,7 +6575,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6751,6 +6838,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6945,55 +7036,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index f56eb19904..e3617c1f4f 100644 --- a/InvenTree/locale/es/LC_MESSAGES/django.po +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Spanish\n" "Language: es_ES\n" @@ -33,42 +33,42 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "Confirmar" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "Confirmar la contraseña" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "Confirmar contraseña nueva" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -122,9 +122,9 @@ msgstr "Comentario" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "Usuario" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "Inglés" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "Francés" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "Alemán" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "Polaco" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "Turco" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "Eliminar elemento" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "Configurar Contraseña" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "Información del sistema" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "Cantidad" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "Unicación" @@ -540,14 +542,14 @@ msgstr "Unicación" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "Estado" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "Referencia" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "Parte" @@ -691,7 +693,7 @@ msgstr "Elementos completados" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "Responsable" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "Notas" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "Número de serie" @@ -921,8 +923,8 @@ msgstr "Número de serie" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "Progreso" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "Lote" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "Guardar" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "días" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "Cliente" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "Fabricantes" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,113 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +#, fuzzy +#| msgid "System Information" +msgid "Order Price Information" +msgstr "Información del sistema" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4640,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4837,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5177,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5327,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5462,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6117,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6158,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6265,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6318,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6491,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6576,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6839,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7037,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7567,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/fr/LC_MESSAGES/django.po b/InvenTree/locale/fr/LC_MESSAGES/django.po index 9f32eeb22f..7db5f3a3d4 100644 --- a/InvenTree/locale/fr/LC_MESSAGES/django.po +++ b/InvenTree/locale/fr/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: French\n" "Language: fr_FR\n" @@ -33,42 +33,42 @@ msgstr "" msgid "Enter date" msgstr "Entrer la date" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "Confirmer" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "Confirmer la suppression" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "Confirmer la suppression de cet élément" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "Entrer le mot de passe" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "Entrer le nouveau mot de passe" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "Confirmez le mot de passe" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "Confirmer le nouveau mot de passe" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -122,9 +122,9 @@ msgstr "Commentaire" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "Description (facultative)" msgid "parent" msgstr "parent" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "Supprimer cet élément" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/it/LC_MESSAGES/django.po b/InvenTree/locale/it/LC_MESSAGES/django.po index 20cbccebaa..d7603d9931 100644 --- a/InvenTree/locale/it/LC_MESSAGES/django.po +++ b/InvenTree/locale/it/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Italian\n" "Language: it_IT\n" @@ -33,42 +33,42 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -122,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/ja/LC_MESSAGES/django.po b/InvenTree/locale/ja/LC_MESSAGES/django.po index fe9b71062e..80c2ab0260 100644 --- a/InvenTree/locale/ja/LC_MESSAGES/django.po +++ b/InvenTree/locale/ja/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Japanese\n" "Language: ja_JP\n" @@ -33,42 +33,42 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -122,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/pl/LC_MESSAGES/django.po b/InvenTree/locale/pl/LC_MESSAGES/django.po index c9c9975b16..9f34636319 100644 --- a/InvenTree/locale/pl/LC_MESSAGES/django.po +++ b/InvenTree/locale/pl/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Polish\n" "Language: pl_PL\n" @@ -33,42 +33,42 @@ msgstr "Nie znaleziono pasującej akcji" msgid "Enter date" msgstr "Wprowadź dane" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "Potwierdź" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "Potwierdź usunięcie" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "Potwierdź usuwanie elementu" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "Wprowadź hasło" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "Wprowadź nowe hasło" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "Potwierdź hasło" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "Potwierdź nowe hasło" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "Zastosuj motyw" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "Wybierz kategorię" @@ -122,9 +122,9 @@ msgstr "Komentarz" msgid "File comment" msgstr "Komentarz pliku" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "Użytkownik" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "data przesłania" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "Opis (opcjonalny)" msgid "parent" msgstr "nadrzędny" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "Angielski" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "Francuski" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "Niemiecki" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "Polski" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "Turecki" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "Zwrócone" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "Wysłane" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "Usuń element" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "Zaznacz pole aby potwierdzić usunięcie elementu" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "Edytuj informacje użytkownika" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "Ustaw hasło" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "Hasła muszą być zgodne" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "Informacja systemowa" @@ -444,10 +444,10 @@ msgstr "Numer Zlecenia Budowy" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "Ilość" @@ -528,11 +530,11 @@ msgstr "Oznacz budowę jako ukończoną" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "Lokalizacja" @@ -540,14 +542,14 @@ msgstr "Lokalizacja" msgid "Location of completed parts" msgstr "Lokalizacja ukończonych części" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "Status" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "Zlecenie Budowy" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "Zlecenia budowy" @@ -602,7 +604,7 @@ msgstr "Odwołanie do zamówienia wykonania" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "Referencja" msgid "Brief description of the build" msgstr "Krótki opis budowy" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "Budowa nadrzędna" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "Zamówienie budowy, do którego budowa jest przypisana" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "Zamówienie budowy, do którego budowa jest przypisana" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "Część" @@ -691,7 +693,7 @@ msgstr "Ukończone elementy" msgid "Number of stock items which have been completed" msgstr "Ilość produktów magazynowych które zostały ukończone" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "Status budowania" @@ -732,10 +734,10 @@ msgstr "Wydany przez" msgid "User who issued this build order" msgstr "Użytkownik, który wydał to zamówienie" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "Odpowiedzialny" @@ -749,8 +751,8 @@ msgstr "Użytkownik odpowiedzialny za to zamówienie budowy" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "Link Zewnętrzny" @@ -768,12 +770,12 @@ msgstr "Link do zewnętrznego adresu URL" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "Uwagi" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "Element magazynowy" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "Numer Seryjny" @@ -921,8 +923,8 @@ msgstr "Numer Seryjny" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "Załączniki" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "Widok administratora" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "Zaległe" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "Akcje druku" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "Wydrukuj Numer Zlecenia Budowy" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "Edytuj Budowę" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "Anuluj Budowę" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "Szczegóły budowy" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "Postęp" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "Zamówienie zakupu" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "Dodane przez" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "Nie określono lokalizacji docelowej" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "Partia" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "Utworzony" @@ -1282,8 +1284,8 @@ msgstr "Edytuj uwagi" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "Zapisz" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "Dodano załącznik" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "Nazwa instancji InvenTree" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "Nazwa firmy" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "Bazowy URL" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "Bazowy adres URL dla instancji serwera" -#: common/models.py:84 -msgid "Default Currency" -msgstr "Domyślna waluta" - #: common/models.py:85 -msgid "Default currency" -msgstr "Domyślna waluta" - -#: common/models.py:91 msgid "Download from URL" msgstr "Pobierz z adresu URL" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "Zezwól na pobieranie zewnętrznych obrazów i plików z zewnętrznego URL" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "Obsługa kodu kreskowego" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "Włącz obsługę skanera kodów" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "Wyrażenie regularne IPN" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "Zezwól na powtarzający się IPN" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "Zezwól na edycję IPN" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "Skopiuj BOM komponentu" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "Szablon" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "Złożenie" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "Komponent" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "Możliwość zakupu" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "Części są domyślnie z możliwością zakupu" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "Możliwość sprzedaży" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "Części są domyślnie z możliwością sprzedaży" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "Możliwość śledzenia" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "Części są domyślnie z możliwością śledzenia" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "Wirtualny" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "Części są domyślnie wirtualne" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "Tryb Debugowania" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "Rozmiar strony" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "Raporty testów" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "Włącz generowanie raportów testów" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "dni" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "Grupuj według komponentu" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "Ustawienia wartości" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "Cena" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "Domyślny" @@ -1882,7 +1876,7 @@ msgstr "URL" msgid "Image URL" msgstr "URL zdjęcia" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "Cena jednostkowa" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "Czy to przedsiębiorstwo produkuje części?" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "Część bazowa" @@ -2011,7 +2005,7 @@ msgstr "Wybierz część" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "Część producenta" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "Opakowanie" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "Klient" @@ -2220,7 +2215,7 @@ msgstr "Usuń części" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "Nowy komponent" @@ -2267,7 +2262,7 @@ msgstr "Utwórz nowego dostawcę części" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "Now dostawca części" @@ -2290,7 +2285,7 @@ msgstr "Lista dostawców" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "Zamów część" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "Dostawcy" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "Stan" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "Informacja cenowa" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "Edytuj przedział cenowy" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "Producenci" @@ -2537,20 +2532,20 @@ msgstr "Firmy" msgid "New Company" msgstr "Nowa firma" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "Pobierz obraz" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "Edytuj przedział cenowy" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "Oznacz zamówienie jako zakończone" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "Anuluj zamówienie" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "Wyślij zamówienie" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "Zamówienie" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "Odebrane" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "Cena zakupu" @@ -2888,8 +2883,9 @@ msgstr "Cena zakupu" msgid "Unit purchase price" msgstr "Cena zakupu jednostkowego" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "Cena sprzedaży" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "Status zamówienia" @@ -2981,7 +2977,7 @@ msgstr "Wydany" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "Nowa lokalizacja" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "Kod zamówienia" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "Usuń linie" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "Akcje" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "Domyślna lokalizacja" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "Dostępna ilość" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "Część nadrzędna" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "Podczęść" @@ -3727,7 +3723,7 @@ msgstr "Domyślne słowa kluczowe" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "Słowa kluczowe" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "Kategoria" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "IPN" @@ -3852,7 +3848,7 @@ msgstr "Minimalny stan magazynowy" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "Jednostki" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "Sprzedaj wiele" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "Nazwa testu" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "Wymagane" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "Dane" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "Wartość domyślna" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "Suma kontrolna" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "Część 1" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "Część 2" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "Wybierz powiązaną część" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "Wszystkie części" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "Stwórz nową kategorię komponentów" @@ -4367,7 +4363,7 @@ msgstr "Parametry" msgid "Part Parameters" msgstr "Parametry części" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "Duplikuj część" @@ -4504,27 +4500,122 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +#, fuzzy +#| msgid "Pricing Information" +msgid "Order Price Information" +msgstr "Informacja cenowa" + +#: part/templates/part/navbar.html:75 +#, fuzzy +#| msgid "Order Parts" +msgid "Order Price" +msgstr "Zamów części" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +#, fuzzy +#| msgid "Pricing Information" +msgid "Pricing ranges" +msgstr "Informacja cenowa" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +#, fuzzy +#| msgid "Pricing" +msgid "Stock Pricing" +msgstr "Cennik" + +#: part/templates/part/order_prices.html:121 +#, fuzzy +#| msgid "No stock available for %(part)s" +msgid "No stock pricing history is available for this part." +msgstr "Brak zapasów dla %(part)s" + +#: part/templates/part/order_prices.html:140 +#, fuzzy, python-format +#| msgid "Single Price" +msgid "Single Price - %(currency)s" +msgstr "Cena jednostkowa" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4649,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4846,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5186,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5336,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5471,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6126,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6167,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6274,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6327,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6500,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6585,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6848,12 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +#, fuzzy +#| msgid "Single Price" +msgid "Single Price Difference" +msgstr "Cena jednostkowa" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7048,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7578,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/ru/LC_MESSAGES/django.po b/InvenTree/locale/ru/LC_MESSAGES/django.po index df6f0336c7..963e03cbd8 100644 --- a/InvenTree/locale/ru/LC_MESSAGES/django.po +++ b/InvenTree/locale/ru/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Russian\n" "Language: ru_RU\n" @@ -33,42 +33,42 @@ msgstr "" msgid "Enter date" msgstr "" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "" @@ -122,9 +122,9 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/tr/LC_MESSAGES/django.po b/InvenTree/locale/tr/LC_MESSAGES/django.po index 9d3d99e1c6..bbd9a9e162 100644 --- a/InvenTree/locale/tr/LC_MESSAGES/django.po +++ b/InvenTree/locale/tr/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 10:47\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Turkish\n" "Language: tr_TR\n" @@ -33,42 +33,42 @@ msgstr "Eşleşen eylem bulunamadı" msgid "Enter date" msgstr "Tarih giriniz" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "Onay" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "Silmeyi Onayla" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "Silmeyi onayla" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "Şifrenizi girin" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "Lütfen Yeni Parolayı Girin" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "Parolayı doğrulayın" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "Yeni parolayı doğrulayın" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "Temayı Uygula" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "Kategori Seçin" @@ -122,9 +122,9 @@ msgstr "Yorum" msgid "File comment" msgstr "Yorum" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "Kullanıcı" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "Yükleme tarihi" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "Açıklama(opsiyonel)" msgid "parent" msgstr "ebeveyn" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "İngilizce" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "Fransızca" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "Almanca" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "Polonyaca" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "Türkçe" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "İade" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "Sevk edildi" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - diff --git a/InvenTree/locale/zh/LC_MESSAGES/django.po b/InvenTree/locale/zh/LC_MESSAGES/django.po index c897b54b5a..71294a33f5 100644 --- a/InvenTree/locale/zh/LC_MESSAGES/django.po +++ b/InvenTree/locale/zh/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: inventree\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-17 10:46+0000\n" -"PO-Revision-Date: 2021-05-17 14:58\n" +"POT-Creation-Date: 2021-05-29 07:28+0000\n" +"PO-Revision-Date: 2021-05-28 04:02\n" "Last-Translator: \n" "Language-Team: Chinese Simplified\n" "Language: zh_CN\n" @@ -33,42 +33,42 @@ msgstr "未找到指定操作" msgid "Enter date" msgstr "输入日期" -#: InvenTree/forms.py:110 build/forms.py:102 build/forms.py:123 +#: InvenTree/forms.py:112 build/forms.py:102 build/forms.py:123 #: build/forms.py:145 build/forms.py:169 build/forms.py:185 build/forms.py:227 #: order/forms.py:27 order/forms.py:38 order/forms.py:49 order/forms.py:60 #: order/forms.py:71 part/forms.py:134 msgid "Confirm" msgstr "确认" -#: InvenTree/forms.py:126 +#: InvenTree/forms.py:128 msgid "Confirm delete" msgstr "确认删除" -#: InvenTree/forms.py:127 +#: InvenTree/forms.py:129 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:159 templates/registration/login.html:77 +#: InvenTree/forms.py:161 templates/registration/login.html:77 msgid "Enter password" msgstr "输入密码" -#: InvenTree/forms.py:160 +#: InvenTree/forms.py:162 msgid "Enter new password" msgstr "输入新密码" -#: InvenTree/forms.py:167 +#: InvenTree/forms.py:169 msgid "Confirm password" msgstr "确认密码" -#: InvenTree/forms.py:168 +#: InvenTree/forms.py:170 msgid "Confirm new password" msgstr "确认新密码" -#: InvenTree/forms.py:203 +#: InvenTree/forms.py:205 msgid "Apply Theme" msgstr "应用主题" -#: InvenTree/forms.py:233 +#: InvenTree/forms.py:235 msgid "Select Category" msgstr "选择分类" @@ -122,9 +122,9 @@ msgstr "注释" msgid "File comment" msgstr "文件注释" -#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1946 +#: InvenTree/models.py:68 InvenTree/models.py:69 part/models.py:1999 #: report/templates/report/inventree_test_report_base.html:91 -#: templates/js/stock.js:1146 +#: templates/js/stock.js:1151 msgid "User" msgstr "用户" @@ -133,7 +133,7 @@ msgid "upload date" msgstr "上传日期" #: InvenTree/models.py:107 InvenTree/models.py:108 label/models.py:102 -#: part/models.py:686 part/models.py:2087 part/templates/part/params.html:27 +#: part/models.py:686 part/models.py:2140 part/templates/part/params.html:27 #: report/models.py:179 templates/InvenTree/search.html:137 #: templates/InvenTree/search.html:289 templates/js/part.js:110 #: templates/js/part.js:553 templates/js/stock.js:944 @@ -171,23 +171,23 @@ msgstr "" msgid "parent" msgstr "" -#: InvenTree/settings.py:501 +#: InvenTree/settings.py:503 msgid "English" msgstr "" -#: InvenTree/settings.py:502 +#: InvenTree/settings.py:504 msgid "French" msgstr "" -#: InvenTree/settings.py:503 +#: InvenTree/settings.py:505 msgid "German" msgstr "" -#: InvenTree/settings.py:504 +#: InvenTree/settings.py:506 msgid "Polish" msgstr "" -#: InvenTree/settings.py:505 +#: InvenTree/settings.py:507 msgid "Turkish" msgstr "" @@ -232,7 +232,7 @@ msgid "Returned" msgstr "" #: InvenTree/status_codes.py:146 -#: order/templates/order/sales_order_base.html:124 +#: order/templates/order/sales_order_base.html:126 msgid "Shipped" msgstr "" @@ -372,27 +372,27 @@ msgstr "" msgid "Overage must be an integer value or a percentage" msgstr "" -#: InvenTree/views.py:587 +#: InvenTree/views.py:592 msgid "Delete Item" msgstr "" -#: InvenTree/views.py:636 +#: InvenTree/views.py:641 msgid "Check box to confirm item deletion" msgstr "" -#: InvenTree/views.py:651 templates/InvenTree/settings/user.html:18 +#: InvenTree/views.py:656 templates/InvenTree/settings/user.html:18 msgid "Edit User Information" msgstr "" -#: InvenTree/views.py:662 templates/InvenTree/settings/user.html:22 +#: InvenTree/views.py:667 templates/InvenTree/settings/user.html:22 msgid "Set Password" msgstr "" -#: InvenTree/views.py:681 +#: InvenTree/views.py:686 msgid "Password fields must match" msgstr "" -#: InvenTree/views.py:887 templates/navbar.html:95 +#: InvenTree/views.py:937 templates/navbar.html:95 msgid "System Information" msgstr "" @@ -444,10 +444,10 @@ msgstr "" msgid "Order target date" msgstr "" -#: build/forms.py:42 build/templates/build/build_base.html:136 +#: build/forms.py:42 build/templates/build/build_base.html:146 #: build/templates/build/detail.html:121 order/forms.py:109 order/forms.py:144 #: order/templates/order/order_base.html:124 -#: order/templates/order/sales_order_base.html:117 +#: order/templates/order/sales_order_base.html:119 #: report/templates/report/inventree_build_order_base.html:126 #: templates/js/build.js:783 templates/js/order.js:200 #: templates/js/order.js:298 @@ -461,8 +461,8 @@ msgstr "" #: build/forms.py:48 build/forms.py:90 build/forms.py:266 build/models.py:1245 #: build/templates/build/allocation_card.html:23 #: build/templates/build/auto_allocate.html:17 -#: build/templates/build/build_base.html:123 -#: build/templates/build/detail.html:31 common/models.py:705 +#: build/templates/build/build_base.html:133 +#: build/templates/build/detail.html:31 common/models.py:699 #: company/forms.py:176 company/templates/company/supplier_part_pricing.html:77 #: order/forms.py:188 order/forms.py:205 order/forms.py:240 order/forms.py:262 #: order/forms.py:279 order/models.py:614 order/models.py:815 @@ -473,20 +473,22 @@ msgstr "" #: order/templates/order/sales_order_detail.html:77 #: order/templates/order/sales_order_detail.html:162 #: order/templates/order/sales_order_detail.html:230 part/forms.py:342 -#: part/forms.py:371 part/forms.py:387 part/models.py:2216 +#: part/forms.py:371 part/forms.py:387 part/models.py:2269 #: part/templates/part/allocation.html:19 #: part/templates/part/allocation.html:53 -#: part/templates/part/part_pricing.html:13 +#: part/templates/part/order_prices.html:175 +#: part/templates/part/part_pricing.html:12 #: part/templates/part/sale_prices.html:85 #: report/templates/report/inventree_build_order_base.html:114 #: report/templates/report/inventree_po_report.html:91 #: report/templates/report/inventree_so_report.html:91 #: report/templates/report/inventree_test_report_base.html:77 #: stock/forms.py:175 stock/forms.py:308 -#: stock/templates/stock/item_base.html:250 +#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:364 #: templates/js/bom.js:205 templates/js/build.js:476 templates/js/build.js:1014 -#: templates/js/stock.js:1131 templates/js/stock.js:1393 +#: templates/js/part.js:717 templates/js/stock.js:1136 +#: templates/js/stock.js:1398 msgid "Quantity" msgstr "" @@ -528,11 +530,11 @@ msgstr "" #: build/forms.py:210 build/templates/build/auto_allocate.html:18 #: order/forms.py:82 stock/forms.py:347 -#: stock/templates/stock/item_base.html:280 +#: stock/templates/stock/item_base.html:285 #: stock/templates/stock/stock_adjust.html:17 #: templates/InvenTree/search.html:260 templates/js/barcode.js:363 #: templates/js/barcode.js:531 templates/js/build.js:490 -#: templates/js/stock.js:641 templates/js/stock.js:1023 +#: templates/js/stock.js:641 templates/js/stock.js:1028 msgid "Location" msgstr "" @@ -540,14 +542,14 @@ msgstr "" msgid "Location of completed parts" msgstr "" -#: build/forms.py:215 build/templates/build/build_base.html:128 +#: build/forms.py:215 build/templates/build/build_base.html:138 #: build/templates/build/detail.html:59 order/models.py:466 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:398 templates/InvenTree/search.html:252 +#: stock/templates/stock/item_base.html:403 templates/InvenTree/search.html:252 #: templates/js/barcode.js:119 templates/js/build.js:770 #: templates/js/order.js:187 templates/js/order.js:285 -#: templates/js/stock.js:628 templates/js/stock.js:1100 -#: templates/js/stock.js:1401 +#: templates/js/stock.js:628 templates/js/stock.js:1105 +#: templates/js/stock.js:1406 msgid "Status" msgstr "" @@ -580,7 +582,7 @@ msgid "Select quantity of stock to allocate" msgstr "" #: build/models.py:65 build/templates/build/build_base.html:9 -#: build/templates/build/build_base.html:63 +#: build/templates/build/build_base.html:73 #: part/templates/part/allocation.html:23 #: report/templates/report/inventree_build_order_base.html:106 msgid "Build Order" @@ -592,7 +594,7 @@ msgstr "" #: order/templates/order/so_navbar.html:22 part/templates/part/navbar.html:55 #: part/templates/part/navbar.html:58 templates/InvenTree/index.html:183 #: templates/InvenTree/search.html:185 -#: templates/InvenTree/settings/tabs.html:31 users/models.py:43 +#: templates/InvenTree/settings/tabs.html:34 users/models.py:43 msgid "Build Orders" msgstr "" @@ -602,7 +604,7 @@ msgstr "" #: build/models.py:127 order/models.py:99 order/models.py:616 #: order/templates/order/purchase_order_detail.html:170 -#: order/templates/order/sales_order_detail.html:225 part/models.py:2225 +#: order/templates/order/sales_order_detail.html:225 part/models.py:2278 #: report/templates/report/inventree_po_report.html:92 #: report/templates/report/inventree_so_report.html:92 templates/js/bom.js:197 #: templates/js/build.js:565 templates/js/build.js:1008 @@ -613,7 +615,7 @@ msgstr "" msgid "Brief description of the build" msgstr "" -#: build/models.py:146 build/templates/build/build_base.html:153 +#: build/models.py:146 build/templates/build/build_base.html:163 #: build/templates/build/detail.html:77 msgid "Parent Build" msgstr "" @@ -623,17 +625,17 @@ msgid "BuildOrder to which this build is allocated" msgstr "" #: build/models.py:152 build/templates/build/auto_allocate.html:16 -#: build/templates/build/build_base.html:118 +#: build/templates/build/build_base.html:128 #: build/templates/build/detail.html:26 company/models.py:622 #: order/models.py:658 order/models.py:691 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:131 #: order/templates/order/receive_parts.html:19 #: order/templates/order/sales_order_detail.html:213 part/models.py:321 -#: part/models.py:1914 part/models.py:1926 part/models.py:1944 -#: part/models.py:2019 part/models.py:2115 part/models.py:2200 +#: part/models.py:1967 part/models.py:1979 part/models.py:1997 +#: part/models.py:2072 part/models.py:2168 part/models.py:2253 #: part/templates/part/part_app_base.html:8 -#: part/templates/part/part_pricing.html:9 part/templates/part/related.html:29 +#: part/templates/part/part_pricing.html:8 part/templates/part/related.html:29 #: part/templates/part/set_category.html:13 #: report/templates/report/inventree_build_order_base.html:110 #: report/templates/report/inventree_po_report.html:90 @@ -643,7 +645,7 @@ msgstr "" #: templates/js/build.js:741 templates/js/build.js:981 #: templates/js/company.js:140 templates/js/company.js:238 #: templates/js/part.js:233 templates/js/part.js:338 templates/js/stock.js:523 -#: templates/js/stock.js:1465 +#: templates/js/stock.js:1470 msgid "Part" msgstr "" @@ -691,7 +693,7 @@ msgstr "" msgid "Number of stock items which have been completed" msgstr "" -#: build/models.py:204 part/templates/part/part_base.html:160 +#: build/models.py:204 part/templates/part/part_base.html:167 msgid "Build Status" msgstr "" @@ -732,10 +734,10 @@ msgstr "" msgid "User who issued this build order" msgstr "" -#: build/models.py:250 build/templates/build/build_base.html:174 +#: build/models.py:250 build/templates/build/build_base.html:184 #: build/templates/build/detail.html:105 order/models.py:119 #: order/templates/order/order_base.html:138 -#: order/templates/order/sales_order_base.html:138 part/models.py:886 +#: order/templates/order/sales_order_base.html:140 part/models.py:886 #: report/templates/report/inventree_build_order_base.html:159 msgid "Responsible" msgstr "" @@ -749,8 +751,8 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:28 #: company/templates/company/supplier_part_base.html:78 #: company/templates/company/supplier_part_detail.html:28 -#: part/templates/part/detail.html:83 part/templates/part/part_base.html:101 -#: stock/models.py:458 stock/templates/stock/item_base.html:340 +#: part/templates/part/detail.html:83 part/templates/part/part_base.html:94 +#: stock/models.py:458 stock/templates/stock/item_base.html:345 msgid "External Link" msgstr "" @@ -768,12 +770,12 @@ msgstr "" #: order/templates/order/sales_order_detail.html:278 #: order/templates/order/so_navbar.html:33 #: order/templates/order/so_navbar.html:36 part/models.py:871 -#: part/templates/part/navbar.html:128 +#: part/templates/part/navbar.html:134 #: report/templates/report/inventree_build_order_base.html:173 #: stock/forms.py:173 stock/forms.py:317 stock/forms.py:349 stock/forms.py:377 #: stock/models.py:530 stock/models.py:1665 stock/models.py:1767 #: stock/templates/stock/navbar.html:57 templates/js/barcode.js:37 -#: templates/js/bom.js:333 templates/js/stock.js:128 templates/js/stock.js:671 +#: templates/js/bom.js:349 templates/js/stock.js:128 templates/js/stock.js:671 msgid "Notes" msgstr "" @@ -823,7 +825,7 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:1224 stock/templates/stock/item_base.html:312 +#: build/models.py:1224 stock/templates/stock/item_base.html:317 #: templates/InvenTree/search.html:183 templates/js/build.js:714 #: templates/navbar.html:29 msgid "Build" @@ -838,10 +840,10 @@ msgstr "" #: part/templates/part/allocation.html:31 #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:8 -#: stock/templates/stock/item_base.html:93 -#: stock/templates/stock/item_base.html:334 +#: stock/templates/stock/item_base.html:31 +#: stock/templates/stock/item_base.html:339 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:831 -#: templates/js/stock.js:1082 templates/js/stock.js:1384 +#: templates/js/stock.js:1087 templates/js/stock.js:1389 msgid "Stock Item" msgstr "" @@ -913,7 +915,7 @@ msgstr "" #: order/templates/order/sales_order_detail.html:75 #: order/templates/order/sales_order_detail.html:160 #: report/templates/report/inventree_test_report_base.html:75 -#: stock/models.py:452 stock/templates/stock/item_base.html:244 +#: stock/models.py:452 stock/templates/stock/item_base.html:249 #: templates/js/build.js:474 msgid "Serial Number" msgstr "" @@ -921,8 +923,8 @@ msgstr "" #: build/templates/build/attachments.html:12 #: build/templates/build/navbar.html:43 build/templates/build/navbar.html:46 #: order/templates/order/po_navbar.html:26 -#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:119 -#: part/templates/part/navbar.html:122 stock/templates/stock/navbar.html:47 +#: order/templates/order/so_navbar.html:29 part/templates/part/navbar.html:125 +#: part/templates/part/navbar.html:128 stock/templates/stock/navbar.html:47 #: stock/templates/stock/navbar.html:50 msgid "Attachments" msgstr "" @@ -943,119 +945,119 @@ msgstr "" msgid "Stock items will have to be manually allocated" msgstr "" -#: build/templates/build/build_base.html:16 +#: build/templates/build/build_base.html:18 #, python-format msgid "This Build Order is allocated to Sales Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:22 +#: build/templates/build/build_base.html:25 #, python-format msgid "This Build Order is a child of Build Order %(link)s" msgstr "" -#: build/templates/build/build_base.html:31 +#: build/templates/build/build_base.html:32 msgid "Build Order is ready to mark as completed" msgstr "" -#: build/templates/build/build_base.html:36 +#: build/templates/build/build_base.html:37 msgid "Build Order cannot be completed as outstanding outputs remain" msgstr "" -#: build/templates/build/build_base.html:41 +#: build/templates/build/build_base.html:42 msgid "Required build quantity has not yet been completed" msgstr "" -#: build/templates/build/build_base.html:46 +#: build/templates/build/build_base.html:47 msgid "Stock has not been fully allocated to this Build Order" msgstr "" -#: build/templates/build/build_base.html:65 +#: build/templates/build/build_base.html:75 #: company/templates/company/company_base.html:40 #: company/templates/company/manufacturer_part_base.html:25 #: company/templates/company/supplier_part_base.html:26 #: order/templates/order/order_base.html:26 -#: order/templates/order/sales_order_base.html:35 -#: part/templates/part/category.html:18 part/templates/part/part_base.html:29 -#: stock/templates/stock/item_base.html:124 +#: order/templates/order/sales_order_base.html:37 +#: part/templates/part/category.html:18 part/templates/part/part_base.html:22 +#: stock/templates/stock/item_base.html:62 #: stock/templates/stock/location.html:31 msgid "Admin view" msgstr "" -#: build/templates/build/build_base.html:71 -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:81 +#: build/templates/build/build_base.html:150 #: order/templates/order/order_base.html:32 #: order/templates/order/order_base.html:86 -#: order/templates/order/sales_order_base.html:41 -#: order/templates/order/sales_order_base.html:86 +#: order/templates/order/sales_order_base.html:43 +#: order/templates/order/sales_order_base.html:88 #: templates/js/table_filters.js:241 templates/js/table_filters.js:260 #: templates/js/table_filters.js:277 msgid "Overdue" msgstr "" -#: build/templates/build/build_base.html:80 +#: build/templates/build/build_base.html:90 msgid "Print actions" msgstr "" -#: build/templates/build/build_base.html:84 +#: build/templates/build/build_base.html:94 msgid "Print Build Order" msgstr "" -#: build/templates/build/build_base.html:90 -#: build/templates/build/build_base.html:215 +#: build/templates/build/build_base.html:100 +#: build/templates/build/build_base.html:225 msgid "Complete Build" msgstr "" -#: build/templates/build/build_base.html:95 +#: build/templates/build/build_base.html:105 msgid "Build actions" msgstr "" -#: build/templates/build/build_base.html:99 +#: build/templates/build/build_base.html:109 msgid "Edit Build" msgstr "" -#: build/templates/build/build_base.html:101 -#: build/templates/build/build_base.html:199 build/views.py:57 +#: build/templates/build/build_base.html:111 +#: build/templates/build/build_base.html:209 build/views.py:57 msgid "Cancel Build" msgstr "" -#: build/templates/build/build_base.html:114 +#: build/templates/build/build_base.html:124 #: build/templates/build/detail.html:11 msgid "Build Details" msgstr "" -#: build/templates/build/build_base.html:140 +#: build/templates/build/build_base.html:150 #, python-format msgid "This build was due on %(target)s" msgstr "" -#: build/templates/build/build_base.html:147 +#: build/templates/build/build_base.html:157 #: build/templates/build/detail.html:64 msgid "Progress" msgstr "" -#: build/templates/build/build_base.html:160 +#: build/templates/build/build_base.html:170 #: build/templates/build/detail.html:84 order/models.py:689 #: order/templates/order/sales_order_base.html:9 -#: order/templates/order/sales_order_base.html:33 +#: order/templates/order/sales_order_base.html:35 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:30 #: report/templates/report/inventree_build_order_base.html:136 #: report/templates/report/inventree_so_report.html:77 -#: stock/templates/stock/item_base.html:274 templates/js/order.js:245 +#: stock/templates/stock/item_base.html:279 templates/js/order.js:245 msgid "Sales Order" msgstr "" -#: build/templates/build/build_base.html:167 +#: build/templates/build/build_base.html:177 #: build/templates/build/detail.html:98 #: report/templates/report/inventree_build_order_base.html:153 msgid "Issued By" msgstr "" -#: build/templates/build/build_base.html:207 +#: build/templates/build/build_base.html:217 msgid "Incomplete Outputs" msgstr "" -#: build/templates/build/build_base.html:208 +#: build/templates/build/build_base.html:218 msgid "Build Order cannot be completed as incomplete build outputs remain" msgstr "" @@ -1191,15 +1193,15 @@ msgid "Destination location not specified" msgstr "" #: build/templates/build/detail.html:70 -#: stock/templates/stock/item_base.html:298 templates/js/stock.js:636 -#: templates/js/stock.js:1408 templates/js/table_filters.js:108 +#: stock/templates/stock/item_base.html:303 templates/js/stock.js:636 +#: templates/js/stock.js:1413 templates/js/table_filters.js:108 #: templates/js/table_filters.js:202 msgid "Batch" msgstr "" #: build/templates/build/detail.html:116 #: order/templates/order/order_base.html:111 -#: order/templates/order/sales_order_base.html:111 templates/js/build.js:778 +#: order/templates/order/sales_order_base.html:113 templates/js/build.js:778 msgid "Created" msgstr "" @@ -1282,8 +1284,8 @@ msgstr "" #: build/templates/build/notes.html:26 company/templates/company/notes.html:24 #: order/templates/order/order_notes.html:27 #: order/templates/order/sales_order_notes.html:29 -#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:477 -#: stock/templates/stock/item_base.html:487 +#: part/templates/part/notes.html:27 stock/templates/stock/item_base.html:482 +#: stock/templates/stock/item_base.html:492 #: stock/templates/stock/item_notes.html:26 msgid "Save" msgstr "" @@ -1429,7 +1431,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:172 +#: build/views.py:1083 order/views.py:115 order/views.py:167 part/views.py:173 #: stock/views.py:277 msgid "Added attachment" msgstr "" @@ -1466,368 +1468,360 @@ msgstr "" msgid "Error reading file (data could be corrupted)" msgstr "" -#: common/forms.py:38 templates/attachment_table.html:15 +#: common/forms.py:39 templates/attachment_table.html:15 msgid "File" msgstr "" -#: common/forms.py:39 +#: common/forms.py:40 msgid "Select file to upload" msgstr "" -#: common/forms.py:54 +#: common/forms.py:55 msgid "{name.title()} File" msgstr "" -#: common/forms.py:55 +#: common/forms.py:56 #, python-brace-format msgid "Select {name} file to upload" msgstr "" -#: common/models.py:58 +#: common/models.py:59 msgid "InvenTree Instance Name" msgstr "" -#: common/models.py:60 +#: common/models.py:61 msgid "String descriptor for the server instance" msgstr "" -#: common/models.py:64 +#: common/models.py:65 msgid "Use instance name" msgstr "" -#: common/models.py:65 +#: common/models.py:66 msgid "Use the instance name in the title-bar" msgstr "" -#: common/models.py:71 company/models.py:94 company/models.py:95 +#: common/models.py:72 company/models.py:94 company/models.py:95 msgid "Company name" msgstr "" -#: common/models.py:72 +#: common/models.py:73 msgid "Internal company name" msgstr "" -#: common/models.py:77 +#: common/models.py:78 msgid "Base URL" msgstr "" -#: common/models.py:78 +#: common/models.py:79 msgid "Base URL for server instance" msgstr "" -#: common/models.py:84 -msgid "Default Currency" -msgstr "" - #: common/models.py:85 -msgid "Default currency" -msgstr "" - -#: common/models.py:91 msgid "Download from URL" msgstr "" -#: common/models.py:92 +#: common/models.py:86 msgid "Allow download of remote images and files from external URL" msgstr "" -#: common/models.py:98 +#: common/models.py:92 msgid "Barcode Support" msgstr "" -#: common/models.py:99 +#: common/models.py:93 msgid "Enable barcode scanner support" msgstr "" -#: common/models.py:105 +#: common/models.py:99 msgid "IPN Regex" msgstr "" -#: common/models.py:106 +#: common/models.py:100 msgid "Regular expression pattern for matching Part IPN" msgstr "" -#: common/models.py:110 +#: common/models.py:104 msgid "Allow Duplicate IPN" msgstr "" -#: common/models.py:111 +#: common/models.py:105 msgid "Allow multiple parts to share the same IPN" msgstr "" -#: common/models.py:117 +#: common/models.py:111 msgid "Allow Editing IPN" msgstr "" -#: common/models.py:118 +#: common/models.py:112 msgid "Allow changing the IPN value while editing a part" msgstr "" -#: common/models.py:124 +#: common/models.py:118 msgid "Copy Part BOM Data" msgstr "" -#: common/models.py:125 +#: common/models.py:119 msgid "Copy BOM data by default when duplicating a part" msgstr "" -#: common/models.py:131 +#: common/models.py:125 msgid "Copy Part Parameter Data" msgstr "" -#: common/models.py:132 +#: common/models.py:126 msgid "Copy parameter data by default when duplicating a part" msgstr "" -#: common/models.py:138 +#: common/models.py:132 msgid "Copy Part Test Data" msgstr "" -#: common/models.py:139 +#: common/models.py:133 msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:145 +#: common/models.py:139 msgid "Copy Category Parameter Templates" msgstr "" -#: common/models.py:146 +#: common/models.py:140 msgid "Copy category parameter templates when creating a part" msgstr "" -#: common/models.py:152 +#: common/models.py:146 msgid "Recent Part Count" msgstr "" -#: common/models.py:153 +#: common/models.py:147 msgid "Number of recent parts to display on index page" msgstr "" -#: common/models.py:159 part/models.py:2117 part/templates/part/detail.html:160 +#: common/models.py:153 part/models.py:2170 part/templates/part/detail.html:160 #: report/models.py:185 stock/forms.py:259 templates/js/table_filters.js:25 #: templates/js/table_filters.js:311 msgid "Template" msgstr "" -#: common/models.py:160 +#: common/models.py:154 msgid "Parts are templates by default" msgstr "" -#: common/models.py:166 part/models.py:834 part/templates/part/detail.html:170 +#: common/models.py:160 part/models.py:834 part/templates/part/detail.html:170 #: templates/js/table_filters.js:124 templates/js/table_filters.js:323 msgid "Assembly" msgstr "" -#: common/models.py:167 +#: common/models.py:161 msgid "Parts can be assembled from other components by default" msgstr "" -#: common/models.py:173 part/models.py:840 part/templates/part/detail.html:180 +#: common/models.py:167 part/models.py:840 part/templates/part/detail.html:180 #: templates/js/table_filters.js:327 msgid "Component" msgstr "" -#: common/models.py:174 +#: common/models.py:168 msgid "Parts can be used as sub-components by default" msgstr "" -#: common/models.py:180 part/models.py:851 part/templates/part/detail.html:200 +#: common/models.py:174 part/models.py:851 part/templates/part/detail.html:200 msgid "Purchaseable" msgstr "" -#: common/models.py:181 +#: common/models.py:175 msgid "Parts are purchaseable by default" msgstr "" -#: common/models.py:187 part/models.py:856 part/templates/part/detail.html:210 +#: common/models.py:181 part/models.py:856 part/templates/part/detail.html:210 #: templates/js/table_filters.js:335 msgid "Salable" msgstr "" -#: common/models.py:188 +#: common/models.py:182 msgid "Parts are salable by default" msgstr "" -#: common/models.py:194 part/models.py:846 part/templates/part/detail.html:190 +#: common/models.py:188 part/models.py:846 part/templates/part/detail.html:190 #: templates/js/table_filters.js:33 templates/js/table_filters.js:339 msgid "Trackable" msgstr "" -#: common/models.py:195 +#: common/models.py:189 msgid "Parts are trackable by default" msgstr "" -#: common/models.py:201 part/models.py:866 part/templates/part/detail.html:150 +#: common/models.py:195 part/models.py:866 part/templates/part/detail.html:150 #: templates/js/table_filters.js:29 msgid "Virtual" msgstr "" -#: common/models.py:202 +#: common/models.py:196 msgid "Parts are virtual by default" msgstr "" -#: common/models.py:208 +#: common/models.py:202 msgid "Show Quantity in Forms" msgstr "" -#: common/models.py:209 +#: common/models.py:203 msgid "Display available part quantity in some forms" msgstr "" -#: common/models.py:215 templates/stats.html:25 +#: common/models.py:209 templates/stats.html:25 msgid "Debug Mode" msgstr "" -#: common/models.py:216 +#: common/models.py:210 msgid "Generate reports in debug mode (HTML output)" msgstr "" -#: common/models.py:222 +#: common/models.py:216 msgid "Page Size" msgstr "" -#: common/models.py:223 +#: common/models.py:217 msgid "Default page size for PDF reports" msgstr "" -#: common/models.py:233 +#: common/models.py:227 msgid "Test Reports" msgstr "" -#: common/models.py:234 +#: common/models.py:228 msgid "Enable generation of test reports" msgstr "" -#: common/models.py:240 +#: common/models.py:234 msgid "Stock Expiry" msgstr "" -#: common/models.py:241 +#: common/models.py:235 msgid "Enable stock expiry functionality" msgstr "" -#: common/models.py:247 +#: common/models.py:241 msgid "Sell Expired Stock" msgstr "" -#: common/models.py:248 +#: common/models.py:242 msgid "Allow sale of expired stock" msgstr "" -#: common/models.py:254 +#: common/models.py:248 msgid "Stock Stale Time" msgstr "" -#: common/models.py:255 +#: common/models.py:249 msgid "Number of days stock items are considered stale before expiring" msgstr "" -#: common/models.py:257 part/templates/part/detail.html:121 +#: common/models.py:251 part/templates/part/detail.html:121 msgid "days" msgstr "" -#: common/models.py:262 +#: common/models.py:256 msgid "Build Expired Stock" msgstr "" -#: common/models.py:263 +#: common/models.py:257 msgid "Allow building with expired stock" msgstr "" -#: common/models.py:269 +#: common/models.py:263 msgid "Stock Ownership Control" msgstr "" -#: common/models.py:270 +#: common/models.py:264 msgid "Enable ownership control over stock locations and items" msgstr "" -#: common/models.py:276 +#: common/models.py:270 msgid "Group by Part" msgstr "" -#: common/models.py:277 +#: common/models.py:271 msgid "Group stock items by part reference in table views" msgstr "" -#: common/models.py:283 +#: common/models.py:277 msgid "Recent Stock Count" msgstr "" -#: common/models.py:284 +#: common/models.py:278 msgid "Number of recent stock items to display on index page" msgstr "" -#: common/models.py:290 +#: common/models.py:284 msgid "Build Order Reference Prefix" msgstr "" -#: common/models.py:291 +#: common/models.py:285 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:296 +#: common/models.py:290 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:297 +#: common/models.py:291 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:301 +#: common/models.py:295 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:302 +#: common/models.py:296 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:307 +#: common/models.py:301 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:308 +#: common/models.py:302 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:531 +#: common/models.py:525 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:533 +#: common/models.py:527 msgid "Settings value" msgstr "" -#: common/models.py:568 +#: common/models.py:562 msgid "Must be an integer value" msgstr "" -#: common/models.py:591 +#: common/models.py:585 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:602 +#: common/models.py:596 msgid "Value must be an integer value" msgstr "" -#: common/models.py:625 +#: common/models.py:619 msgid "Key string must be unique" msgstr "" -#: common/models.py:706 company/forms.py:177 +#: common/models.py:700 company/forms.py:177 msgid "Price break quantity" msgstr "" -#: common/models.py:714 company/templates/company/supplier_part_pricing.html:82 -#: part/templates/part/sale_prices.html:90 templates/js/bom.js:255 +#: common/models.py:708 company/templates/company/supplier_part_pricing.html:82 +#: part/templates/part/sale_prices.html:90 templates/js/bom.js:271 msgid "Price" msgstr "" -#: common/models.py:715 +#: common/models.py:709 msgid "Unit price at specified quantity" msgstr "" -#: common/models.py:804 +#: common/models.py:798 msgid "Default" msgstr "" @@ -1882,7 +1876,7 @@ msgstr "" msgid "Image URL" msgstr "" -#: company/forms.py:118 +#: company/forms.py:118 templates/js/part.js:708 msgid "Single Price" msgstr "" @@ -1998,7 +1992,7 @@ msgid "Does this company manufacture parts?" msgstr "" #: company/models.py:305 company/models.py:456 stock/models.py:405 -#: stock/templates/stock/item_base.html:230 +#: stock/templates/stock/item_base.html:235 msgid "Base Part" msgstr "" @@ -2011,7 +2005,7 @@ msgstr "" #: company/templates/company/manufacturer_part_detail.html:25 #: company/templates/company/supplier_part_base.html:94 #: company/templates/company/supplier_part_detail.html:34 part/bom.py:170 -#: part/bom.py:241 stock/templates/stock/item_base.html:347 +#: part/bom.py:241 stock/templates/stock/item_base.html:352 #: templates/js/company.js:44 templates/js/company.js:165 #: templates/js/company.js:289 msgid "Manufacturer" @@ -2030,7 +2024,7 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:25 order/models.py:190 #: order/templates/order/order_base.html:92 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:175 -#: part/bom.py:286 stock/templates/stock/item_base.html:359 +#: part/bom.py:286 stock/templates/stock/item_base.html:364 #: templates/js/company.js:48 templates/js/company.js:263 #: templates/js/order.js:170 msgid "Supplier" @@ -2054,7 +2048,7 @@ msgstr "" #: company/models.py:479 #: company/templates/company/manufacturer_part_base.html:6 #: company/templates/company/manufacturer_part_base.html:19 -#: stock/templates/stock/item_base.html:352 +#: stock/templates/stock/item_base.html:357 msgid "Manufacturer Part" msgstr "" @@ -2071,7 +2065,7 @@ msgid "Supplier part description" msgstr "" #: company/models.py:497 company/templates/company/supplier_part_base.html:116 -#: company/templates/company/supplier_part_detail.html:38 part/models.py:2228 +#: company/templates/company/supplier_part_detail.html:38 part/models.py:2281 #: report/templates/report/inventree_po_report.html:93 #: report/templates/report/inventree_so_report.html:93 msgid "Note" @@ -2086,7 +2080,7 @@ msgid "Minimum charge (e.g. stocking fee)" msgstr "" #: company/models.py:503 company/templates/company/supplier_part_base.html:109 -#: stock/models.py:429 stock/templates/stock/item_base.html:305 +#: stock/models.py:429 stock/templates/stock/item_base.html:310 #: templates/js/stock.js:667 msgid "Packaging" msgstr "" @@ -2154,7 +2148,8 @@ msgstr "" #: company/templates/company/delete.html:12 #, python-format -msgid "There are %(count)s parts sourced from this company.
    \n" +msgid "" +"There are %(count)s parts sourced from this company.
    \n" "If this supplier is deleted, these supplier part entries will also be deleted." msgstr "" @@ -2171,10 +2166,10 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:67 order/models.py:461 -#: order/templates/order/sales_order_base.html:92 stock/models.py:447 -#: stock/models.py:448 stock/templates/stock/item_base.html:257 +#: order/templates/order/sales_order_base.html:94 stock/models.py:447 +#: stock/models.py:448 stock/templates/stock/item_base.html:262 #: templates/js/company.js:40 templates/js/order.js:267 -#: templates/js/stock.js:1064 +#: templates/js/stock.js:1069 msgid "Customer" msgstr "" @@ -2220,7 +2215,7 @@ msgstr "" #: company/templates/company/detail_manufacturer_part.html:66 #: company/templates/company/detail_supplier_part.html:66 #: part/templates/part/bom.html:159 part/templates/part/category.html:118 -#: templates/js/stock.js:1279 +#: templates/js/stock.js:1284 msgid "New Part" msgstr "" @@ -2267,7 +2262,7 @@ msgstr "" #: company/templates/company/detail_supplier_part.html:22 #: company/templates/company/manufacturer_part_suppliers.html:17 #: order/templates/order/purchase_order_detail.html:49 -#: part/templates/part/supplier.html:17 templates/js/stock.js:1285 +#: part/templates/part/supplier.html:17 templates/js/stock.js:1290 msgid "New Supplier Part" msgstr "" @@ -2290,7 +2285,7 @@ msgstr "" #: company/templates/company/manufacturer_part_base.html:36 #: company/templates/company/supplier_part_base.html:36 #: company/templates/company/supplier_part_orders.html:17 -#: part/templates/part/orders.html:17 part/templates/part/part_base.html:65 +#: part/templates/part/orders.html:17 part/templates/part/part_base.html:58 msgid "Order part" msgstr "" @@ -2324,8 +2319,8 @@ msgid "There are %(count)s suppliers defined for this manufacturer part. If you msgstr "" #: company/templates/company/manufacturer_part_navbar.html:14 -#: company/views.py:63 part/templates/part/navbar.html:78 -#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:316 +#: company/views.py:63 part/templates/part/navbar.html:84 +#: part/templates/part/navbar.html:87 templates/InvenTree/search.html:316 #: templates/navbar.html:35 msgid "Suppliers" msgstr "" @@ -2342,7 +2337,7 @@ msgstr "" #: stock/templates/stock/stock_app_base.html:10 #: templates/InvenTree/index.html:128 templates/InvenTree/search.html:196 #: templates/InvenTree/search.html:232 -#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:173 +#: templates/InvenTree/settings/tabs.html:31 templates/js/part.js:173 #: templates/js/part.js:398 templates/js/stock.js:563 templates/navbar.html:26 msgid "Stock" msgstr "" @@ -2400,10 +2395,10 @@ msgstr "" #: company/templates/company/sales_orders.html:11 #: order/templates/order/sales_orders.html:8 #: order/templates/order/sales_orders.html:13 -#: part/templates/part/navbar.html:98 part/templates/part/navbar.html:101 +#: part/templates/part/navbar.html:104 part/templates/part/navbar.html:107 #: part/templates/part/sales_orders.html:10 templates/InvenTree/index.html:228 #: templates/InvenTree/search.html:345 -#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:46 +#: templates/InvenTree/settings/tabs.html:40 templates/navbar.html:46 #: users/models.py:45 msgid "Sales Orders" msgstr "" @@ -2412,10 +2407,10 @@ msgstr "" #: company/templates/company/purchase_orders.html:10 #: order/templates/order/purchase_orders.html:8 #: order/templates/order/purchase_orders.html:13 -#: part/templates/part/navbar.html:84 part/templates/part/navbar.html:87 +#: part/templates/part/navbar.html:90 part/templates/part/navbar.html:93 #: part/templates/part/orders.html:10 templates/InvenTree/index.html:205 #: templates/InvenTree/search.html:325 -#: templates/InvenTree/settings/tabs.html:34 templates/navbar.html:37 +#: templates/InvenTree/settings/tabs.html:37 templates/navbar.html:37 #: users/models.py:44 msgid "Purchase Orders" msgstr "" @@ -2446,7 +2441,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:7 #: company/templates/company/supplier_part_base.html:20 stock/models.py:414 -#: stock/templates/stock/item_base.html:364 templates/js/company.js:279 +#: stock/templates/stock/item_base.html:369 templates/js/company.js:279 msgid "Supplier Part" msgstr "" @@ -2495,7 +2490,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:19 company/views.py:794 -#: part/templates/part/sale_prices.html:17 part/views.py:2644 +#: part/templates/part/sale_prices.html:17 part/views.py:2733 msgid "Add Price Break" msgstr "" @@ -2514,8 +2509,8 @@ msgstr "" msgid "Delete price break" msgstr "" -#: company/views.py:70 part/templates/part/navbar.html:72 -#: part/templates/part/navbar.html:75 templates/InvenTree/search.html:306 +#: company/views.py:70 part/templates/part/navbar.html:78 +#: part/templates/part/navbar.html:81 templates/InvenTree/search.html:306 #: templates/navbar.html:36 msgid "Manufacturers" msgstr "" @@ -2537,20 +2532,20 @@ msgstr "" msgid "New Company" msgstr "" -#: company/views.py:169 part/views.py:848 +#: company/views.py:169 part/views.py:937 msgid "Download Image" msgstr "" -#: company/views.py:198 part/views.py:880 +#: company/views.py:198 part/views.py:969 msgid "Image size exceeds maximum allowable size for download" msgstr "" -#: company/views.py:205 part/views.py:887 +#: company/views.py:205 part/views.py:976 #, python-brace-format msgid "Invalid response: {code}" msgstr "" -#: company/views.py:214 part/views.py:896 +#: company/views.py:214 part/views.py:985 msgid "Supplied URL is not a valid image file" msgstr "" @@ -2602,7 +2597,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:578 templates/js/stock.js:1286 +#: company/views.py:578 templates/js/stock.js:1291 msgid "Create new Supplier Part" msgstr "" @@ -2610,15 +2605,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:799 part/views.py:2648 +#: company/views.py:799 part/views.py:2737 msgid "Added new price break" msgstr "" -#: company/views.py:855 part/views.py:2692 +#: company/views.py:855 part/views.py:2781 msgid "Edit Price Break" msgstr "" -#: company/views.py:870 part/views.py:2706 +#: company/views.py:870 part/views.py:2795 msgid "Delete Price Break" msgstr "" @@ -2692,11 +2687,11 @@ msgid "Mark order as complete" msgstr "" #: order/forms.py:49 order/forms.py:60 order/templates/order/order_base.html:59 -#: order/templates/order/sales_order_base.html:59 +#: order/templates/order/sales_order_base.html:61 msgid "Cancel order" msgstr "" -#: order/forms.py:71 order/templates/order/sales_order_base.html:56 +#: order/forms.py:71 order/templates/order/sales_order_base.html:58 msgid "Ship order" msgstr "" @@ -2793,7 +2788,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:243 part/views.py:1586 stock/models.py:302 +#: order/models.py:243 part/views.py:1675 stock/models.py:302 #: stock/models.py:1018 msgid "Quantity must be greater than zero" msgstr "" @@ -2859,8 +2854,8 @@ msgstr "" #: order/models.py:645 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: report/templates/report/inventree_po_report.html:77 -#: stock/templates/stock/item_base.html:319 templates/js/order.js:148 -#: templates/js/stock.js:1045 +#: stock/templates/stock/item_base.html:324 templates/js/order.js:148 +#: templates/js/stock.js:1050 msgid "Purchase Order" msgstr "" @@ -2871,7 +2866,7 @@ msgstr "" #: order/models.py:662 order/templates/order/order_base.html:131 #: order/templates/order/purchase_order_detail.html:189 #: order/templates/order/receive_parts.html:22 -#: order/templates/order/sales_order_base.html:131 +#: order/templates/order/sales_order_base.html:133 msgid "Received" msgstr "" @@ -2880,7 +2875,7 @@ msgid "Number of items received" msgstr "" #: order/models.py:669 stock/models.py:540 -#: stock/templates/stock/item_base.html:326 +#: stock/templates/stock/item_base.html:331 msgid "Purchase Price" msgstr "" @@ -2888,8 +2883,9 @@ msgstr "" msgid "Unit purchase price" msgstr "" -#: order/models.py:698 part/templates/part/navbar.html:95 -#: part/templates/part/part_pricing.html:78 +#: order/models.py:698 part/templates/part/navbar.html:101 +#: part/templates/part/order_prices.html:82 +#: part/templates/part/part_pricing.html:77 msgid "Sale Price" msgstr "" @@ -2940,12 +2936,12 @@ msgid "Are you sure you want to delete this attachment?" msgstr "" #: order/templates/order/order_base.html:39 -#: order/templates/order/sales_order_base.html:48 +#: order/templates/order/sales_order_base.html:50 msgid "Print" msgstr "" #: order/templates/order/order_base.html:43 -#: order/templates/order/sales_order_base.html:52 +#: order/templates/order/sales_order_base.html:54 msgid "Edit order information" msgstr "" @@ -2963,12 +2959,12 @@ msgid "Purchase Order Details" msgstr "" #: order/templates/order/order_base.html:77 -#: order/templates/order/sales_order_base.html:77 +#: order/templates/order/sales_order_base.html:79 msgid "Order Reference" msgstr "" #: order/templates/order/order_base.html:82 -#: order/templates/order/sales_order_base.html:82 +#: order/templates/order/sales_order_base.html:84 msgid "Order Status" msgstr "" @@ -2981,7 +2977,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:100 #: part/templates/part/category.html:185 part/templates/part/category.html:227 #: stock/templates/stock/location.html:191 templates/js/stock.js:708 -#: templates/js/stock.js:1291 +#: templates/js/stock.js:1296 msgid "New Location" msgstr "" @@ -3193,14 +3189,14 @@ msgstr "" msgid "Receive outstanding parts for %(order)s - %(desc)s" msgstr "" -#: order/templates/order/receive_parts.html:14 part/api.py:40 +#: order/templates/order/receive_parts.html:14 part/api.py:45 #: part/models.py:322 part/templates/part/cat_link.html:7 #: part/templates/part/category.html:99 #: part/templates/part/category_navbar.html:22 #: part/templates/part/category_navbar.html:29 #: part/templates/part/category_partlist.html:10 #: templates/InvenTree/index.html:97 templates/InvenTree/search.html:114 -#: templates/InvenTree/settings/tabs.html:25 templates/js/part.js:577 +#: templates/InvenTree/settings/tabs.html:28 templates/js/part.js:577 #: templates/navbar.html:23 templates/stats.html:80 templates/stats.html:89 #: users/models.py:40 msgid "Parts" @@ -3215,7 +3211,7 @@ msgid "Order Code" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.js:414 +#: part/templates/part/part_base.html:136 templates/js/part.js:414 msgid "On Order" msgstr "" @@ -3231,20 +3227,20 @@ msgstr "" msgid "Remove line" msgstr "" -#: order/templates/order/sales_order_base.html:15 -msgid "This SalesOrder has not been fully allocated" +#: order/templates/order/sales_order_base.html:16 +msgid "This Sales Order has not been fully allocated" msgstr "" -#: order/templates/order/sales_order_base.html:64 +#: order/templates/order/sales_order_base.html:66 msgid "Packing List" msgstr "" -#: order/templates/order/sales_order_base.html:72 +#: order/templates/order/sales_order_base.html:74 #: order/templates/order/so_navbar.html:12 msgid "Sales Order Details" msgstr "" -#: order/templates/order/sales_order_base.html:98 templates/js/order.js:275 +#: order/templates/order/sales_order_base.html:100 templates/js/order.js:275 msgid "Customer Reference" msgstr "" @@ -3263,7 +3259,7 @@ msgstr "" msgid "Sales Order Items" msgstr "" -#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:342 +#: order/templates/order/sales_order_detail.html:95 templates/js/bom.js:358 #: templates/js/build.js:627 templates/js/build.js:1044 msgid "Actions" msgstr "" @@ -3558,7 +3554,7 @@ msgstr "" msgid "Default Location" msgstr "" -#: part/bom.py:139 part/templates/part/part_base.html:117 +#: part/bom.py:139 part/templates/part/part_base.html:124 msgid "Available Stock" msgstr "" @@ -3631,7 +3627,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:122 part/models.py:2115 +#: part/forms.py:122 part/models.py:2168 msgid "Parent Part" msgstr "" @@ -3707,7 +3703,7 @@ msgstr "" msgid "Add parameter template to all categories" msgstr "" -#: part/forms.py:344 part/models.py:2209 +#: part/forms.py:344 part/models.py:2262 msgid "Sub part" msgstr "" @@ -3727,7 +3723,7 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:82 part/models.py:2161 +#: part/models.py:82 part/models.py:2214 #: part/templates/part/part_app_base.html:10 msgid "Part Category" msgstr "" @@ -3797,7 +3793,7 @@ msgstr "" msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:724 part/models.py:2160 part/templates/part/detail.html:73 +#: part/models.py:724 part/models.py:2213 part/templates/part/detail.html:73 #: part/templates/part/set_category.html:15 templates/js/part.js:385 msgid "Category" msgstr "" @@ -3807,7 +3803,7 @@ msgid "Part category" msgstr "" #: part/models.py:730 part/templates/part/detail.html:28 -#: part/templates/part/part_base.html:94 templates/js/part.js:161 +#: part/templates/part/part_base.html:87 templates/js/part.js:161 msgid "IPN" msgstr "" @@ -3852,7 +3848,7 @@ msgstr "" msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:828 part/models.py:2089 part/templates/part/detail.html:106 +#: part/models.py:828 part/models.py:2142 part/templates/part/detail.html:106 #: part/templates/part/params.html:29 msgid "Units" msgstr "" @@ -3923,167 +3919,167 @@ msgstr "" msgid "Sell multiple" msgstr "" -#: part/models.py:1987 +#: part/models.py:2040 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:2004 +#: part/models.py:2057 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:2024 templates/js/part.js:638 templates/js/stock.js:104 +#: part/models.py:2077 templates/js/part.js:638 templates/js/stock.js:104 msgid "Test Name" msgstr "" -#: part/models.py:2025 +#: part/models.py:2078 msgid "Enter a name for the test" msgstr "" -#: part/models.py:2030 +#: part/models.py:2083 msgid "Test Description" msgstr "" -#: part/models.py:2031 +#: part/models.py:2084 msgid "Enter description for this test" msgstr "" -#: part/models.py:2036 templates/js/part.js:647 +#: part/models.py:2089 templates/js/part.js:647 #: templates/js/table_filters.js:223 msgid "Required" msgstr "" -#: part/models.py:2037 +#: part/models.py:2090 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:2042 templates/js/part.js:655 +#: part/models.py:2095 templates/js/part.js:655 msgid "Requires Value" msgstr "" -#: part/models.py:2043 +#: part/models.py:2096 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:2048 templates/js/part.js:662 +#: part/models.py:2101 templates/js/part.js:662 msgid "Requires Attachment" msgstr "" -#: part/models.py:2049 +#: part/models.py:2102 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:2082 +#: part/models.py:2135 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:2087 +#: part/models.py:2140 msgid "Parameter Name" msgstr "" -#: part/models.py:2089 +#: part/models.py:2142 msgid "Parameter Units" msgstr "" -#: part/models.py:2117 part/models.py:2166 part/models.py:2167 +#: part/models.py:2170 part/models.py:2219 part/models.py:2220 #: templates/InvenTree/settings/category.html:62 msgid "Parameter Template" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Data" msgstr "" -#: part/models.py:2119 +#: part/models.py:2172 msgid "Parameter Value" msgstr "" -#: part/models.py:2171 templates/InvenTree/settings/category.html:67 +#: part/models.py:2224 templates/InvenTree/settings/category.html:67 msgid "Default Value" msgstr "" -#: part/models.py:2172 +#: part/models.py:2225 msgid "Default Parameter Value" msgstr "" -#: part/models.py:2201 +#: part/models.py:2254 msgid "Select parent part" msgstr "" -#: part/models.py:2210 +#: part/models.py:2263 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:2216 +#: part/models.py:2269 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:2218 templates/js/bom.js:216 templates/js/bom.js:269 +#: part/models.py:2271 templates/js/bom.js:216 templates/js/bom.js:285 msgid "Optional" msgstr "" -#: part/models.py:2218 +#: part/models.py:2271 msgid "This BOM item is optional" msgstr "" -#: part/models.py:2221 +#: part/models.py:2274 msgid "Overage" msgstr "" -#: part/models.py:2222 +#: part/models.py:2275 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:2225 +#: part/models.py:2278 msgid "BOM item reference" msgstr "" -#: part/models.py:2228 +#: part/models.py:2281 msgid "BOM item notes" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "Checksum" msgstr "" -#: part/models.py:2230 +#: part/models.py:2283 msgid "BOM line checksum" msgstr "" -#: part/models.py:2234 templates/js/bom.js:279 templates/js/bom.js:286 +#: part/models.py:2287 templates/js/bom.js:295 templates/js/bom.js:302 #: templates/js/table_filters.js:51 msgid "Inherited" msgstr "" -#: part/models.py:2235 +#: part/models.py:2288 msgid "This BOM item is inherited by BOMs for variant parts" msgstr "" -#: part/models.py:2311 part/views.py:1592 part/views.py:1644 +#: part/models.py:2364 part/views.py:1681 part/views.py:1733 #: stock/models.py:292 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:2320 part/models.py:2322 +#: part/models.py:2373 part/models.py:2375 msgid "Sub part must be specified" msgstr "" -#: part/models.py:2325 +#: part/models.py:2378 msgid "BOM Item" msgstr "" -#: part/models.py:2442 +#: part/models.py:2495 msgid "Part 1" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Part 2" msgstr "" -#: part/models.py:2446 +#: part/models.py:2499 msgid "Select Related Part" msgstr "" -#: part/models.py:2478 +#: part/models.py:2531 msgid "Error creating relationship: check that the part is not related to itself and that the relationship is unique" msgstr "" @@ -4151,7 +4147,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:61 part/views.py:1887 +#: part/templates/part/bom.html:61 part/views.py:1976 msgid "Export Bill of Materials" msgstr "" @@ -4167,8 +4163,8 @@ msgstr "" msgid "All selected BOM items will be deleted" msgstr "" -#: part/templates/part/bom.html:160 part/views.py:584 -#: templates/js/stock.js:1280 +#: part/templates/part/bom.html:160 part/views.py:585 +#: templates/js/stock.js:1285 msgid "Create New Part" msgstr "" @@ -4249,7 +4245,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:29 part/views.py:2290 +#: part/templates/part/category.html:29 part/views.py:2379 msgid "Create new part category" msgstr "" @@ -4367,7 +4363,7 @@ msgstr "" msgid "Part Parameters" msgstr "" -#: part/templates/part/copy_part.html:9 part/views.py:460 +#: part/templates/part/copy_part.html:9 part/views.py:461 msgid "Duplicate Part" msgstr "" @@ -4504,27 +4500,111 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/navbar.html:92 +#: part/templates/part/navbar.html:72 part/templates/part/order_prices.html:12 +msgid "Order Price Information" +msgstr "" + +#: part/templates/part/navbar.html:75 +msgid "Order Price" +msgstr "" + +#: part/templates/part/navbar.html:98 msgid "Sales Price Information" msgstr "" -#: part/templates/part/navbar.html:106 part/templates/part/part_tests.html:10 +#: part/templates/part/navbar.html:112 part/templates/part/part_tests.html:10 msgid "Part Test Templates" msgstr "" -#: part/templates/part/navbar.html:109 stock/templates/stock/item_base.html:404 +#: part/templates/part/navbar.html:115 stock/templates/stock/item_base.html:409 msgid "Tests" msgstr "" -#: part/templates/part/navbar.html:113 part/templates/part/navbar.html:116 +#: part/templates/part/navbar.html:119 part/templates/part/navbar.html:122 #: part/templates/part/related.html:10 msgid "Related Parts" msgstr "" -#: part/templates/part/navbar.html:125 part/templates/part/notes.html:12 +#: part/templates/part/navbar.html:131 part/templates/part/notes.html:12 msgid "Part Notes" msgstr "" +#: part/templates/part/order_prices.html:21 +msgid "Pricing ranges" +msgstr "" + +#: part/templates/part/order_prices.html:26 +#: part/templates/part/part_pricing.html:18 +msgid "Supplier Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:27 +#: part/templates/part/order_prices.html:52 +#: part/templates/part/order_prices.html:83 +#: part/templates/part/part_pricing.html:22 +#: part/templates/part/part_pricing.html:48 +#: part/templates/part/part_pricing.html:80 +msgid "Unit Cost" +msgstr "" + +#: part/templates/part/order_prices.html:34 +#: part/templates/part/order_prices.html:59 +#: part/templates/part/order_prices.html:88 +#: part/templates/part/part_pricing.html:28 +#: part/templates/part/part_pricing.html:54 +#: part/templates/part/part_pricing.html:84 +msgid "Total Cost" +msgstr "" + +#: part/templates/part/order_prices.html:42 +#: part/templates/part/part_pricing.html:36 +msgid "No supplier pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:51 +#: part/templates/part/order_prices.html:103 +#: part/templates/part/part_pricing.html:44 +msgid "BOM Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:67 +#: part/templates/part/part_pricing.html:62 +msgid "Note: BOM pricing is incomplete for this part" +msgstr "" + +#: part/templates/part/order_prices.html:74 +#: part/templates/part/part_pricing.html:69 +msgid "No BOM pricing available" +msgstr "" + +#: part/templates/part/order_prices.html:97 +#: part/templates/part/part_pricing.html:93 +msgid "No pricing information is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:113 +msgid "Stock Pricing" +msgstr "" + +#: part/templates/part/order_prices.html:121 +msgid "No stock pricing history is available for this part." +msgstr "" + +#: part/templates/part/order_prices.html:140 +#, python-format +msgid "Single Price - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:152 +#, python-format +msgid "Single Price Difference - %(currency)s" +msgstr "" + +#: part/templates/part/order_prices.html:163 +#, python-format +msgid "Part Single Price - %(currency)s" +msgstr "" + #: part/templates/part/params.html:17 msgid "Add new parameter" msgstr "" @@ -4558,126 +4638,94 @@ msgstr "" msgid "Part List" msgstr "" -#: part/templates/part/part_base.html:18 -#, python-format -msgid "This part is a variant of %(link)s" -msgstr "" - -#: part/templates/part/part_base.html:33 templates/js/company.js:156 +#: part/templates/part/part_base.html:26 templates/js/company.js:156 #: templates/js/company.js:254 templates/js/part.js:76 templates/js/part.js:153 msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:40 +#: part/templates/part/part_base.html:33 msgid "Star this part" msgstr "" -#: part/templates/part/part_base.html:47 -#: stock/templates/stock/item_base.html:137 +#: part/templates/part/part_base.html:40 +#: stock/templates/stock/item_base.html:75 #: stock/templates/stock/location.html:51 msgid "Barcode actions" msgstr "" -#: part/templates/part/part_base.html:49 -#: stock/templates/stock/item_base.html:139 +#: part/templates/part/part_base.html:42 +#: stock/templates/stock/item_base.html:77 #: stock/templates/stock/location.html:53 templates/qr_button.html:1 msgid "Show QR Code" msgstr "" -#: part/templates/part/part_base.html:50 -#: stock/templates/stock/item_base.html:155 +#: part/templates/part/part_base.html:43 +#: stock/templates/stock/item_base.html:93 #: stock/templates/stock/location.html:54 msgid "Print Label" msgstr "" -#: part/templates/part/part_base.html:55 +#: part/templates/part/part_base.html:48 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:59 +#: part/templates/part/part_base.html:52 msgid "Count part stock" msgstr "" -#: part/templates/part/part_base.html:74 +#: part/templates/part/part_base.html:67 msgid "Part actions" msgstr "" -#: part/templates/part/part_base.html:77 +#: part/templates/part/part_base.html:70 msgid "Duplicate part" msgstr "" -#: part/templates/part/part_base.html:80 +#: part/templates/part/part_base.html:73 msgid "Edit part" msgstr "" -#: part/templates/part/part_base.html:83 +#: part/templates/part/part_base.html:76 msgid "Delete part" msgstr "" -#: part/templates/part/part_base.html:123 templates/js/table_filters.js:157 +#: part/templates/part/part_base.html:107 +msgid "This is a virtual part" +msgstr "" + +#: part/templates/part/part_base.html:113 +#, python-format +msgid "This part is a variant of %(link)s" +msgstr "" + +#: part/templates/part/part_base.html:130 templates/js/table_filters.js:157 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:136 templates/InvenTree/index.html:131 +#: part/templates/part/part_base.html:143 templates/InvenTree/index.html:131 msgid "Required for Build Orders" msgstr "" -#: part/templates/part/part_base.html:143 +#: part/templates/part/part_base.html:150 msgid "Required for Sales Orders" msgstr "" -#: part/templates/part/part_base.html:150 +#: part/templates/part/part_base.html:157 msgid "Allocated to Orders" msgstr "" -#: part/templates/part/part_base.html:165 templates/js/bom.js:300 +#: part/templates/part/part_base.html:172 templates/js/bom.js:316 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:171 templates/js/part.js:418 +#: part/templates/part/part_base.html:178 templates/js/part.js:418 msgid "Building" msgstr "" -#: part/templates/part/part_base.html:250 +#: part/templates/part/part_base.html:257 msgid "Calculate" msgstr "" -#: part/templates/part/part_pricing.html:19 -msgid "Supplier Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:23 -#: part/templates/part/part_pricing.html:49 -#: part/templates/part/part_pricing.html:81 -msgid "Unit Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:29 -#: part/templates/part/part_pricing.html:55 -#: part/templates/part/part_pricing.html:85 -msgid "Total Cost" -msgstr "" - -#: part/templates/part/part_pricing.html:37 -msgid "No supplier pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:45 -msgid "BOM Pricing" -msgstr "" - -#: part/templates/part/part_pricing.html:63 -msgid "Note: BOM pricing is incomplete for this part" -msgstr "" - -#: part/templates/part/part_pricing.html:70 -msgid "No BOM pricing available" -msgstr "" - -#: part/templates/part/part_pricing.html:94 -msgid "No pricing information is available for this part." -msgstr "" - #: part/templates/part/part_tests.html:17 msgid "Add Test Template" msgstr "" @@ -4787,212 +4835,212 @@ msgstr "" msgid "Unknown database" msgstr "" -#: part/views.py:89 +#: part/views.py:90 msgid "Add Related Part" msgstr "" -#: part/views.py:144 +#: part/views.py:145 msgid "Delete Related Part" msgstr "" -#: part/views.py:158 +#: part/views.py:159 msgid "Add part attachment" msgstr "" -#: part/views.py:211 templates/attachment_table.html:32 +#: part/views.py:212 templates/attachment_table.html:32 msgid "Edit attachment" msgstr "" -#: part/views.py:215 +#: part/views.py:216 msgid "Part attachment updated" msgstr "" -#: part/views.py:230 +#: part/views.py:231 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:238 +#: part/views.py:239 msgid "Deleted part attachment" msgstr "" -#: part/views.py:247 +#: part/views.py:248 msgid "Create Test Template" msgstr "" -#: part/views.py:274 +#: part/views.py:275 msgid "Edit Test Template" msgstr "" -#: part/views.py:288 +#: part/views.py:289 msgid "Delete Test Template" msgstr "" -#: part/views.py:295 +#: part/views.py:296 msgid "Set Part Category" msgstr "" -#: part/views.py:345 +#: part/views.py:346 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:380 +#: part/views.py:381 msgid "Create Variant" msgstr "" -#: part/views.py:465 +#: part/views.py:466 msgid "Copied part" msgstr "" -#: part/views.py:519 part/views.py:657 +#: part/views.py:520 part/views.py:658 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:589 +#: part/views.py:590 msgid "Created new part" msgstr "" -#: part/views.py:825 +#: part/views.py:914 msgid "Part QR Code" msgstr "" -#: part/views.py:927 +#: part/views.py:1016 msgid "Upload Part Image" msgstr "" -#: part/views.py:933 part/views.py:968 +#: part/views.py:1022 part/views.py:1057 msgid "Updated part image" msgstr "" -#: part/views.py:942 +#: part/views.py:1031 msgid "Select Part Image" msgstr "" -#: part/views.py:971 +#: part/views.py:1060 msgid "Part image not found" msgstr "" -#: part/views.py:982 +#: part/views.py:1071 msgid "Edit Part Properties" msgstr "" -#: part/views.py:1017 +#: part/views.py:1106 msgid "Duplicate BOM" msgstr "" -#: part/views.py:1047 +#: part/views.py:1136 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:1068 +#: part/views.py:1157 msgid "Validate BOM" msgstr "" -#: part/views.py:1089 +#: part/views.py:1178 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:1100 +#: part/views.py:1189 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1234 +#: part/views.py:1323 msgid "No BOM file provided" msgstr "" -#: part/views.py:1595 +#: part/views.py:1684 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1620 part/views.py:1623 +#: part/views.py:1709 part/views.py:1712 msgid "Select valid part" msgstr "" -#: part/views.py:1629 +#: part/views.py:1718 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1667 +#: part/views.py:1756 msgid "Select a part" msgstr "" -#: part/views.py:1673 +#: part/views.py:1762 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1677 +#: part/views.py:1766 msgid "Specify quantity" msgstr "" -#: part/views.py:1939 +#: part/views.py:2028 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1946 +#: part/views.py:2035 msgid "Part was deleted" msgstr "" -#: part/views.py:1955 +#: part/views.py:2044 msgid "Part Pricing" msgstr "" -#: part/views.py:2089 +#: part/views.py:2178 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:2099 +#: part/views.py:2188 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:2106 +#: part/views.py:2195 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:2114 +#: part/views.py:2203 msgid "Create Part Parameter" msgstr "" -#: part/views.py:2164 +#: part/views.py:2253 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:2178 +#: part/views.py:2267 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2238 +#: part/views.py:2327 msgid "Edit Part Category" msgstr "" -#: part/views.py:2276 +#: part/views.py:2365 msgid "Delete Part Category" msgstr "" -#: part/views.py:2282 +#: part/views.py:2371 msgid "Part category was deleted" msgstr "" -#: part/views.py:2334 +#: part/views.py:2423 msgid "Create Category Parameter Template" msgstr "" -#: part/views.py:2435 +#: part/views.py:2524 msgid "Edit Category Parameter Template" msgstr "" -#: part/views.py:2491 +#: part/views.py:2580 msgid "Delete Category Parameter Template" msgstr "" -#: part/views.py:2510 +#: part/views.py:2599 msgid "Create BOM Item" msgstr "" -#: part/views.py:2580 +#: part/views.py:2669 msgid "Edit BOM item" msgstr "" -#: part/views.py:2636 +#: part/views.py:2725 msgid "Confim BOM item deletion" msgstr "" @@ -5127,7 +5175,7 @@ msgid "Moved {n} parts to {loc}" msgstr "" #: stock/forms.py:114 stock/forms.py:418 stock/models.py:507 -#: stock/templates/stock/item_base.html:371 templates/js/stock.js:656 +#: stock/templates/stock/item_base.html:376 templates/js/stock.js:656 msgid "Expiry Date" msgstr "" @@ -5277,7 +5325,7 @@ msgstr "" msgid "Packaging this stock item is stored in" msgstr "" -#: stock/models.py:435 stock/templates/stock/item_base.html:265 +#: stock/models.py:435 stock/templates/stock/item_base.html:270 msgid "Installed In" msgstr "" @@ -5412,173 +5460,173 @@ msgstr "" msgid "Stock Item Attachments" msgstr "" -#: stock/templates/stock/item_base.html:24 -msgid "You are not in the list of owners of this item. This stock item cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:31 -msgid "This stock item is in production and cannot be edited." -msgstr "" - -#: stock/templates/stock/item_base.html:32 -msgid "Edit the stock item from the build view." -msgstr "" - -#: stock/templates/stock/item_base.html:45 -msgid "This stock item has not passed all required tests" -msgstr "" - -#: stock/templates/stock/item_base.html:53 -#, python-format -msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:61 -#, python-format -msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" -msgstr "" - -#: stock/templates/stock/item_base.html:67 -msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." -msgstr "" - -#: stock/templates/stock/item_base.html:71 -msgid "This stock item cannot be deleted as it has child items" -msgstr "" - -#: stock/templates/stock/item_base.html:75 -msgid "This stock item will be automatically deleted when all stock is depleted." -msgstr "" - -#: stock/templates/stock/item_base.html:95 -#: stock/templates/stock/item_base.html:375 templates/js/table_filters.js:146 +#: stock/templates/stock/item_base.html:33 +#: stock/templates/stock/item_base.html:380 templates/js/table_filters.js:146 msgid "Expired" msgstr "" -#: stock/templates/stock/item_base.html:105 -#: stock/templates/stock/item_base.html:377 templates/js/table_filters.js:151 +#: stock/templates/stock/item_base.html:43 +#: stock/templates/stock/item_base.html:382 templates/js/table_filters.js:151 msgid "Stale" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/js/barcode.js:309 +#: stock/templates/stock/item_base.html:80 templates/js/barcode.js:309 #: templates/js/barcode.js:314 msgid "Unlink Barcode" msgstr "" -#: stock/templates/stock/item_base.html:144 +#: stock/templates/stock/item_base.html:82 msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:146 templates/stock_table.html:31 +#: stock/templates/stock/item_base.html:84 templates/stock_table.html:31 msgid "Scan to Location" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:91 msgid "Printing actions" msgstr "" -#: stock/templates/stock/item_base.html:157 +#: stock/templates/stock/item_base.html:95 #: stock/templates/stock/item_tests.html:27 msgid "Test Report" msgstr "" -#: stock/templates/stock/item_base.html:166 +#: stock/templates/stock/item_base.html:104 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:170 +#: stock/templates/stock/item_base.html:108 #: stock/templates/stock/location.html:65 templates/stock_table.html:57 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:173 templates/stock_table.html:55 +#: stock/templates/stock/item_base.html:111 templates/stock_table.html:55 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:176 templates/stock_table.html:56 +#: stock/templates/stock/item_base.html:114 templates/stock_table.html:56 msgid "Remove stock" msgstr "" -#: stock/templates/stock/item_base.html:179 +#: stock/templates/stock/item_base.html:117 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:183 +#: stock/templates/stock/item_base.html:121 msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:186 +#: stock/templates/stock/item_base.html:124 msgid "Assign to customer" msgstr "" -#: stock/templates/stock/item_base.html:189 +#: stock/templates/stock/item_base.html:127 msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:193 templates/js/stock.js:1421 +#: stock/templates/stock/item_base.html:131 templates/js/stock.js:1426 msgid "Uninstall stock item" msgstr "" -#: stock/templates/stock/item_base.html:193 +#: stock/templates/stock/item_base.html:131 msgid "Uninstall" msgstr "" -#: stock/templates/stock/item_base.html:202 +#: stock/templates/stock/item_base.html:140 #: stock/templates/stock/location.html:62 msgid "Stock actions" msgstr "" -#: stock/templates/stock/item_base.html:205 +#: stock/templates/stock/item_base.html:143 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:208 +#: stock/templates/stock/item_base.html:146 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:210 +#: stock/templates/stock/item_base.html:148 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:213 +#: stock/templates/stock/item_base.html:151 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:225 +#: stock/templates/stock/item_base.html:171 +msgid "You are not in the list of owners of this item. This stock item cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:178 +msgid "This stock item is in production and cannot be edited." +msgstr "" + +#: stock/templates/stock/item_base.html:179 +msgid "Edit the stock item from the build view." +msgstr "" + +#: stock/templates/stock/item_base.html:192 +msgid "This stock item has not passed all required tests" +msgstr "" + +#: stock/templates/stock/item_base.html:200 +#, python-format +msgid "This stock item is allocated to Sales Order %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:208 +#, python-format +msgid "This stock item is allocated to Build %(link)s (Quantity: %(qty)s)" +msgstr "" + +#: stock/templates/stock/item_base.html:214 +msgid "This stock item is serialized - it has a unique serial number and the quantity cannot be adjusted." +msgstr "" + +#: stock/templates/stock/item_base.html:218 +msgid "This stock item cannot be deleted as it has child items" +msgstr "" + +#: stock/templates/stock/item_base.html:222 +msgid "This stock item will be automatically deleted when all stock is depleted." +msgstr "" + +#: stock/templates/stock/item_base.html:230 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:284 templates/js/build.js:498 +#: stock/templates/stock/item_base.html:289 templates/js/build.js:498 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:291 +#: stock/templates/stock/item_base.html:296 msgid "Barcode Identifier" msgstr "" -#: stock/templates/stock/item_base.html:333 +#: stock/templates/stock/item_base.html:338 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:375 +#: stock/templates/stock/item_base.html:380 #, python-format msgid "This StockItem expired on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:377 +#: stock/templates/stock/item_base.html:382 #, python-format msgid "This StockItem expires on %(item.expiry_date)s" msgstr "" -#: stock/templates/stock/item_base.html:384 templates/js/stock.js:662 +#: stock/templates/stock/item_base.html:389 templates/js/stock.js:662 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:389 +#: stock/templates/stock/item_base.html:394 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:393 +#: stock/templates/stock/item_base.html:398 msgid "No stocktake performed" msgstr "" @@ -6067,7 +6115,8 @@ msgstr "" #: templates/InvenTree/settings/appearance.html:29 #, python-format -msgid "\n" +msgid "" +"\n" " The CSS sheet \"%(invalid_color_theme)s.css\" for the currently selected color theme was not found.
    \n" " Please select another color theme :)\n" " " @@ -6107,11 +6156,35 @@ msgstr "" msgid "Delete Template" msgstr "" +#: templates/InvenTree/settings/currencies.html:10 +msgid "Currency Settings" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:18 +msgid "Base Currency" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:22 +msgid "Exchange Rates" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:32 +msgid "Last Update" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:38 +msgid "Never" +msgstr "" + +#: templates/InvenTree/settings/currencies.html:43 +msgid "Update Now" +msgstr "" + #: templates/InvenTree/settings/global.html:10 msgid "Global InvenTree Settings" msgstr "" -#: templates/InvenTree/settings/global.html:27 +#: templates/InvenTree/settings/global.html:26 msgid "Barcode Settings" msgstr "" @@ -6190,10 +6263,14 @@ msgid "Global" msgstr "" #: templates/InvenTree/settings/tabs.html:19 -msgid "Report" +msgid "Currencies" msgstr "" #: templates/InvenTree/settings/tabs.html:22 +msgid "Report" +msgstr "" + +#: templates/InvenTree/settings/tabs.html:25 msgid "Categories" msgstr "" @@ -6239,46 +6316,50 @@ msgid "Update Available" msgstr "" #: templates/about.html:34 +msgid "API Version" +msgstr "" + +#: templates/about.html:39 msgid "Django Version" msgstr "" -#: templates/about.html:41 +#: templates/about.html:46 msgid "Commit Hash" msgstr "" -#: templates/about.html:48 +#: templates/about.html:53 msgid "Commit Date" msgstr "" -#: templates/about.html:53 +#: templates/about.html:58 msgid "InvenTree Documentation" msgstr "" -#: templates/about.html:58 +#: templates/about.html:63 msgid "View Code on GitHub" msgstr "" -#: templates/about.html:63 +#: templates/about.html:68 msgid "Credits" msgstr "" -#: templates/about.html:68 +#: templates/about.html:73 msgid "Mobile App" msgstr "" -#: templates/about.html:73 +#: templates/about.html:78 msgid "Submit Bug Report" msgstr "" -#: templates/about.html:80 templates/clip.html:4 +#: templates/about.html:85 templates/clip.html:4 msgid "copy to clipboard" msgstr "" -#: templates/about.html:80 +#: templates/about.html:85 msgid "copy version information" msgstr "" -#: templates/about.html:90 templates/js/modals.js:568 +#: templates/about.html:95 templates/js/modals.js:568 #: templates/js/modals.js:846 templates/modals.html:29 templates/modals.html:54 #: templates/modals.html:97 msgid "Close" @@ -6408,41 +6489,49 @@ msgstr "" msgid "Open subassembly" msgstr "" -#: templates/js/bom.js:261 +#: templates/js/bom.js:249 +msgid "Purchase Price Range" +msgstr "" + +#: templates/js/bom.js:257 +msgid "Purchase Price Average" +msgstr "" + +#: templates/js/bom.js:277 msgid "No pricing available" msgstr "" -#: templates/js/bom.js:272 templates/js/filters.js:167 +#: templates/js/bom.js:288 templates/js/filters.js:167 #: templates/js/filters.js:397 msgid "true" msgstr "" -#: templates/js/bom.js:273 templates/js/filters.js:171 +#: templates/js/bom.js:289 templates/js/filters.js:171 #: templates/js/filters.js:398 msgid "false" msgstr "" -#: templates/js/bom.js:290 templates/js/bom.js:376 +#: templates/js/bom.js:306 templates/js/bom.js:392 msgid "View BOM" msgstr "" -#: templates/js/bom.js:350 +#: templates/js/bom.js:366 msgid "Validate BOM Item" msgstr "" -#: templates/js/bom.js:352 +#: templates/js/bom.js:368 msgid "This line has been validated" msgstr "" -#: templates/js/bom.js:354 +#: templates/js/bom.js:370 msgid "Edit BOM Item" msgstr "" -#: templates/js/bom.js:356 +#: templates/js/bom.js:372 msgid "Delete BOM Item" msgstr "" -#: templates/js/bom.js:447 templates/js/build.js:340 templates/js/build.js:1092 +#: templates/js/bom.js:463 templates/js/build.js:340 templates/js/build.js:1092 msgid "No BOM items found" msgstr "" @@ -6485,7 +6574,7 @@ msgstr "" #: templates/js/build.js:708 templates/js/part.js:324 templates/js/part.js:546 #: templates/js/stock.js:511 templates/js/stock.js:938 -#: templates/js/stock.js:1453 +#: templates/js/stock.js:1458 msgid "Select" msgstr "" @@ -6748,6 +6837,10 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" +#: templates/js/part.js:727 +msgid "Single Price Difference" +msgstr "" + #: templates/js/report.js:47 msgid "items selected" msgstr "" @@ -6942,55 +7035,55 @@ msgstr "" msgid "Invalid date" msgstr "" -#: templates/js/stock.js:1036 +#: templates/js/stock.js:1041 msgid "Location no longer exists" msgstr "" -#: templates/js/stock.js:1055 +#: templates/js/stock.js:1060 msgid "Purchase order no longer exists" msgstr "" -#: templates/js/stock.js:1074 +#: templates/js/stock.js:1079 msgid "Customer no longer exists" msgstr "" -#: templates/js/stock.js:1092 +#: templates/js/stock.js:1097 msgid "Stock item no longer exists" msgstr "" -#: templates/js/stock.js:1115 +#: templates/js/stock.js:1120 msgid "Added" msgstr "" -#: templates/js/stock.js:1123 +#: templates/js/stock.js:1128 msgid "Removed" msgstr "" -#: templates/js/stock.js:1155 +#: templates/js/stock.js:1160 msgid "No user information" msgstr "" -#: templates/js/stock.js:1167 +#: templates/js/stock.js:1172 msgid "Edit tracking entry" msgstr "" -#: templates/js/stock.js:1168 +#: templates/js/stock.js:1173 msgid "Delete tracking entry" msgstr "" -#: templates/js/stock.js:1292 +#: templates/js/stock.js:1297 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1391 +#: templates/js/stock.js:1396 msgid "Serial" msgstr "" -#: templates/js/stock.js:1484 templates/js/table_filters.js:172 +#: templates/js/stock.js:1489 templates/js/table_filters.js:172 msgid "Installed" msgstr "" -#: templates/js/stock.js:1509 +#: templates/js/stock.js:1514 msgid "Install item" msgstr "" @@ -7472,4 +7565,3 @@ msgstr "" #: users/models.py:187 msgid "Permission to delete items" msgstr "" - From 878e9c1e8a552e2fc185b015baf5107cbec23681 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 29 May 2021 17:35:05 +1000 Subject: [PATCH 244/300] Update version.py Bump to v2.2 --- InvenTree/InvenTree/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 67962c7859..709c5e3d77 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -8,7 +8,7 @@ import re import common.models -INVENTREE_SW_VERSION = "0.2.2 pre" +INVENTREE_SW_VERSION = "0.2.2" """ Increment thi API version number whenever there is a significant change to the API that any clients need to know about From 8d33dc579555958f4765d4a0ce5163e02ee9c350 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 29 May 2021 17:48:40 +1000 Subject: [PATCH 245/300] Tag with release tag --- .github/workflows/docker_publish.yaml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker_publish.yaml b/.github/workflows/docker_publish.yaml index 4a8cef0952..c04f9a413d 100644 --- a/.github/workflows/docker_publish.yaml +++ b/.github/workflows/docker_publish.yaml @@ -17,16 +17,17 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - name: cd - run: | - cd docker - - name: Push to Docker Hub - uses: docker/build-push-action@v1 + - name: Login to Dockerhub + uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - repository: inventree/inventree - tag_with_ref: true - dockerfile: ./Dockerfile - target: production + - name: Build and Push + uses: docker/build-push-action@v2 + with: + context: ./docker platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + target: production + repository: inventree/inventree + tags: inventree/inventree:{{ github.event.release.tag_name }} From 52ab8b8064a83ae19ed89c3b15ec26d823fe90e9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 29 May 2021 18:28:07 +1000 Subject: [PATCH 246/300] Update docker_publish.yaml Add $ --- .github/workflows/docker_publish.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker_publish.yaml b/.github/workflows/docker_publish.yaml index c04f9a413d..53ec505003 100644 --- a/.github/workflows/docker_publish.yaml +++ b/.github/workflows/docker_publish.yaml @@ -30,4 +30,4 @@ jobs: push: true target: production repository: inventree/inventree - tags: inventree/inventree:{{ github.event.release.tag_name }} + tags: inventree/inventree:${{ github.event.release.tag_name }} From f08c83d6e50802385b71ba39b5707ffe02a1ab03 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 29 May 2021 18:48:18 +1000 Subject: [PATCH 247/300] Fix part page heading --- InvenTree/part/templates/part/category.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index b79ee0ee60..2e6ebb7fca 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -138,7 +138,7 @@

    {% block heading %} - {% trans "Part Categories" %} + {% trans "Parts" %} {% endblock %}

    From dff367b0b0c957367d24cbeff41b5b923c6c067d Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 29 May 2021 19:05:41 +1000 Subject: [PATCH 248/300] Update version.py --- InvenTree/InvenTree/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 709c5e3d77..a736bfe6a1 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -8,7 +8,7 @@ import re import common.models -INVENTREE_SW_VERSION = "0.2.2" +INVENTREE_SW_VERSION = "0.2.3 pre" """ Increment thi API version number whenever there is a significant change to the API that any clients need to know about From 8450029c68d45a46fb4f079b27f1402904da4044 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 29 May 2021 23:59:07 +1000 Subject: [PATCH 249/300] Add custom-view plugin for bootstrap-table --- .../bootstrap-table-custom-view.js | 1256 ++ .../bootstrap/bootstrap-table-en-US.min.js | 17 +- .../script/bootstrap/bootstrap-table.js | 10392 +++++++++++----- 3 files changed, 8283 insertions(+), 3382 deletions(-) create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js diff --git a/InvenTree/InvenTree/static/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js b/InvenTree/InvenTree/static/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js new file mode 100644 index 0000000000..e4dc26de37 --- /dev/null +++ b/InvenTree/InvenTree/static/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.js @@ -0,0 +1,1256 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) : + typeof define === 'function' && define.amd ? define(['jquery'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jQuery)); +}(this, (function ($) { 'use strict'; + + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + + var $__default = /*#__PURE__*/_interopDefaultLegacy($); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; + } + + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; + } + + function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var check = function (it) { + return it && it.Math == Math && it; + }; + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global_1 = + /* global globalThis -- safe */ + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof commonjsGlobal == 'object' && commonjsGlobal) || + // eslint-disable-next-line no-new-func -- fallback + (function () { return this; })() || Function('return this')(); + + var fails = function (exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + + // Detect IE8's incomplete defineProperty implementation + var descriptors = !fails(function () { + return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; + }); + + var nativePropertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor; + + // Nashorn ~ JDK8 bug + var NASHORN_BUG = getOwnPropertyDescriptor$1 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1); + + // `Object.prototype.propertyIsEnumerable` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable + var f$4 = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor$1(this, V); + return !!descriptor && descriptor.enumerable; + } : nativePropertyIsEnumerable; + + var objectPropertyIsEnumerable = { + f: f$4 + }; + + var createPropertyDescriptor = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + + var toString = {}.toString; + + var classofRaw = function (it) { + return toString.call(it).slice(8, -1); + }; + + var split = ''.split; + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var indexedObject = fails(function () { + // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 + // eslint-disable-next-line no-prototype-builtins -- safe + return !Object('z').propertyIsEnumerable(0); + }) ? function (it) { + return classofRaw(it) == 'String' ? split.call(it, '') : Object(it); + } : Object; + + // `RequireObjectCoercible` abstract operation + // https://tc39.es/ecma262/#sec-requireobjectcoercible + var requireObjectCoercible = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; + }; + + // toObject with fallback for non-array-like ES3 strings + + + + var toIndexedObject = function (it) { + return indexedObject(requireObjectCoercible(it)); + }; + + var isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; + + // `ToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-toprimitive + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + var toPrimitive = function (input, PREFERRED_STRING) { + if (!isObject(input)) return input; + var fn, val; + if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; + if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + throw TypeError("Can't convert object to primitive value"); + }; + + var hasOwnProperty = {}.hasOwnProperty; + + var has$1 = function (it, key) { + return hasOwnProperty.call(it, key); + }; + + var document$1 = global_1.document; + // typeof document.createElement is 'object' in old IE + var EXISTS = isObject(document$1) && isObject(document$1.createElement); + + var documentCreateElement = function (it) { + return EXISTS ? document$1.createElement(it) : {}; + }; + + // Thank's IE8 for his funny defineProperty + var ie8DomDefine = !descriptors && !fails(function () { + return Object.defineProperty(documentCreateElement('div'), 'a', { + get: function () { return 7; } + }).a != 7; + }); + + var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + var f$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject(O); + P = toPrimitive(P, true); + if (ie8DomDefine) try { + return nativeGetOwnPropertyDescriptor(O, P); + } catch (error) { /* empty */ } + if (has$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]); + }; + + var objectGetOwnPropertyDescriptor = { + f: f$3 + }; + + var anObject = function (it) { + if (!isObject(it)) { + throw TypeError(String(it) + ' is not an object'); + } return it; + }; + + var nativeDefineProperty = Object.defineProperty; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (ie8DomDefine) try { + return nativeDefineProperty(O, P, Attributes); + } catch (error) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + + var objectDefineProperty = { + f: f$2 + }; + + var createNonEnumerableProperty = descriptors ? function (object, key, value) { + return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + + var setGlobal = function (key, value) { + try { + createNonEnumerableProperty(global_1, key, value); + } catch (error) { + global_1[key] = value; + } return value; + }; + + var SHARED = '__core-js_shared__'; + var store$1 = global_1[SHARED] || setGlobal(SHARED, {}); + + var sharedStore = store$1; + + var functionToString = Function.toString; + + // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper + if (typeof sharedStore.inspectSource != 'function') { + sharedStore.inspectSource = function (it) { + return functionToString.call(it); + }; + } + + var inspectSource = sharedStore.inspectSource; + + var WeakMap$1 = global_1.WeakMap; + + var nativeWeakMap = typeof WeakMap$1 === 'function' && /native code/.test(inspectSource(WeakMap$1)); + + var shared = createCommonjsModule(function (module) { + (module.exports = function (key, value) { + return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: '3.9.1', + mode: 'global', + copyright: '© 2021 Denis Pushkarev (zloirock.ru)' + }); + }); + + var id = 0; + var postfix = Math.random(); + + var uid = function (key) { + return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36); + }; + + var keys = shared('keys'); + + var sharedKey = function (key) { + return keys[key] || (keys[key] = uid(key)); + }; + + var hiddenKeys$1 = {}; + + var WeakMap = global_1.WeakMap; + var set, get, has; + + var enforce = function (it) { + return has(it) ? get(it) : set(it, {}); + }; + + var getterFor = function (TYPE) { + return function (it) { + var state; + if (!isObject(it) || (state = get(it)).type !== TYPE) { + throw TypeError('Incompatible receiver, ' + TYPE + ' required'); + } return state; + }; + }; + + if (nativeWeakMap) { + var store = sharedStore.state || (sharedStore.state = new WeakMap()); + var wmget = store.get; + var wmhas = store.has; + var wmset = store.set; + set = function (it, metadata) { + metadata.facade = it; + wmset.call(store, it, metadata); + return metadata; + }; + get = function (it) { + return wmget.call(store, it) || {}; + }; + has = function (it) { + return wmhas.call(store, it); + }; + } else { + var STATE = sharedKey('state'); + hiddenKeys$1[STATE] = true; + set = function (it, metadata) { + metadata.facade = it; + createNonEnumerableProperty(it, STATE, metadata); + return metadata; + }; + get = function (it) { + return has$1(it, STATE) ? it[STATE] : {}; + }; + has = function (it) { + return has$1(it, STATE); + }; + } + + var internalState = { + set: set, + get: get, + has: has, + enforce: enforce, + getterFor: getterFor + }; + + var redefine = createCommonjsModule(function (module) { + var getInternalState = internalState.get; + var enforceInternalState = internalState.enforce; + var TEMPLATE = String(String).split('String'); + + (module.exports = function (O, key, value, options) { + var unsafe = options ? !!options.unsafe : false; + var simple = options ? !!options.enumerable : false; + var noTargetGet = options ? !!options.noTargetGet : false; + var state; + if (typeof value == 'function') { + if (typeof key == 'string' && !has$1(value, 'name')) { + createNonEnumerableProperty(value, 'name', key); + } + state = enforceInternalState(value); + if (!state.source) { + state.source = TEMPLATE.join(typeof key == 'string' ? key : ''); + } + } + if (O === global_1) { + if (simple) O[key] = value; + else setGlobal(key, value); + return; + } else if (!unsafe) { + delete O[key]; + } else if (!noTargetGet && O[key]) { + simple = true; + } + if (simple) O[key] = value; + else createNonEnumerableProperty(O, key, value); + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + })(Function.prototype, 'toString', function toString() { + return typeof this == 'function' && getInternalState(this).source || inspectSource(this); + }); + }); + + var path = global_1; + + var aFunction$1 = function (variable) { + return typeof variable == 'function' ? variable : undefined; + }; + + var getBuiltIn = function (namespace, method) { + return arguments.length < 2 ? aFunction$1(path[namespace]) || aFunction$1(global_1[namespace]) + : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; + }; + + var ceil = Math.ceil; + var floor = Math.floor; + + // `ToInteger` abstract operation + // https://tc39.es/ecma262/#sec-tointeger + var toInteger = function (argument) { + return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument); + }; + + var min$1 = Math.min; + + // `ToLength` abstract operation + // https://tc39.es/ecma262/#sec-tolength + var toLength = function (argument) { + return argument > 0 ? min$1(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 + }; + + var max$1 = Math.max; + var min = Math.min; + + // Helper for a popular repeating case of the spec: + // Let integer be ? ToInteger(index). + // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). + var toAbsoluteIndex = function (index, length) { + var integer = toInteger(index); + return integer < 0 ? max$1(integer + length, 0) : min(integer, length); + }; + + // `Array.prototype.{ indexOf, includes }` methods implementation + var createMethod$1 = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare -- NaN check + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare -- NaN check + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + + var arrayIncludes = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod$1(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod$1(false) + }; + + var indexOf = arrayIncludes.indexOf; + + + var objectKeysInternal = function (object, names) { + var O = toIndexedObject(object); + var i = 0; + var result = []; + var key; + for (key in O) !has$1(hiddenKeys$1, key) && has$1(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has$1(O, key = names[i++])) { + ~indexOf(result, key) || result.push(key); + } + return result; + }; + + // IE8- don't enum bug keys + var enumBugKeys = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + var hiddenKeys = enumBugKeys.concat('length', 'prototype'); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return objectKeysInternal(O, hiddenKeys); + }; + + var objectGetOwnPropertyNames = { + f: f$1 + }; + + var f = Object.getOwnPropertySymbols; + + var objectGetOwnPropertySymbols = { + f: f + }; + + // all object keys, includes non-enumerable and symbols + var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { + var keys = objectGetOwnPropertyNames.f(anObject(it)); + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys; + }; + + var copyConstructorProperties = function (target, source) { + var keys = ownKeys(source); + var defineProperty = objectDefineProperty.f; + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!has$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + }; + + var replacement = /#|\.prototype\./; + + var isForced = function (feature, detection) { + var value = data[normalize(feature)]; + return value == POLYFILL ? true + : value == NATIVE ? false + : typeof detection == 'function' ? fails(detection) + : !!detection; + }; + + var normalize = isForced.normalize = function (string) { + return String(string).replace(replacement, '.').toLowerCase(); + }; + + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = 'N'; + var POLYFILL = isForced.POLYFILL = 'P'; + + var isForced_1 = isForced; + + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + + + + + + + /* + options.target - name of the target object + options.global - target is the global object + options.stat - export as static methods of target + options.proto - export as prototype methods of target + options.real - real prototype method for the `pure` version + options.forced - export even if the native feature is available + options.bind - bind methods to the target, required for the `pure` version + options.wrap - wrap constructors to preventing global pollution, required for the `pure` version + options.unsafe - use the simple assignment of property instead of delete + defineProperty + options.sham - add a flag to not completely full polyfills + options.enumerable - export as enumerable property + options.noTargetGet - prevent calling a getter on target + */ + var _export = function (options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = global_1; + } else if (STATIC) { + target = global_1[TARGET] || setGlobal(TARGET, {}); + } else { + target = (global_1[TARGET] || {}).prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.noTargetGet) { + descriptor = getOwnPropertyDescriptor(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); + // contained in target + if (!FORCED && targetProperty !== undefined) { + if (typeof sourceProperty === typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + // add a flag to not completely full polyfills + if (options.sham || (targetProperty && targetProperty.sham)) { + createNonEnumerableProperty(sourceProperty, 'sham', true); + } + // extend global + redefine(target, key, sourceProperty, options); + } + }; + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + var objectKeys = Object.keys || function keys(O) { + return objectKeysInternal(O, enumBugKeys); + }; + + // `ToObject` abstract operation + // https://tc39.es/ecma262/#sec-toobject + var toObject = function (argument) { + return Object(requireObjectCoercible(argument)); + }; + + var nativeAssign = Object.assign; + var defineProperty = Object.defineProperty; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + var objectAssign = !nativeAssign || fails(function () { + // should have correct order of operations (Edge bug) + if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty({}, 'a', { + enumerable: true, + get: function () { + defineProperty(this, 'b', { + value: 3, + enumerable: false + }); + } + }), { b: 2 })).b !== 1) return true; + // should work with symbols and should have deterministic property order (V8 bug) + var A = {}; + var B = {}; + /* global Symbol -- required for testing */ + var symbol = Symbol(); + var alphabet = 'abcdefghijklmnopqrst'; + A[symbol] = 7; + alphabet.split('').forEach(function (chr) { B[chr] = chr; }); + return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet; + }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length` + var T = toObject(target); + var argumentsLength = arguments.length; + var index = 1; + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + var propertyIsEnumerable = objectPropertyIsEnumerable.f; + while (argumentsLength > index) { + var S = indexedObject(arguments[index++]); + var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) { + key = keys[j++]; + if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key]; + } + } return T; + } : nativeAssign; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + _export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, { + assign: objectAssign + }); + + // `IsArray` abstract operation + // https://tc39.es/ecma262/#sec-isarray + var isArray = Array.isArray || function isArray(arg) { + return classofRaw(arg) == 'Array'; + }; + + var createProperty = function (object, key, value) { + var propertyKey = toPrimitive(key); + if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value)); + else object[propertyKey] = value; + }; + + var engineIsNode = classofRaw(global_1.process) == 'process'; + + var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; + + var process = global_1.process; + var versions = process && process.versions; + var v8 = versions && versions.v8; + var match, version; + + if (v8) { + match = v8.split('.'); + version = match[0] + match[1]; + } else if (engineUserAgent) { + match = engineUserAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = engineUserAgent.match(/Chrome\/(\d+)/); + if (match) version = match[1]; + } + } + + var engineV8Version = version && +version; + + var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { + /* global Symbol -- required for testing */ + return !Symbol.sham && + // Chrome 38 Symbol has incorrect toString conversion + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41); + }); + + var useSymbolAsUid = nativeSymbol + /* global Symbol -- safe */ + && !Symbol.sham + && typeof Symbol.iterator == 'symbol'; + + var WellKnownSymbolsStore = shared('wks'); + var Symbol$1 = global_1.Symbol; + var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; + + var wellKnownSymbol = function (name) { + if (!has$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { + if (nativeSymbol && has$1(Symbol$1, name)) { + WellKnownSymbolsStore[name] = Symbol$1[name]; + } else { + WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + } + } return WellKnownSymbolsStore[name]; + }; + + var SPECIES$2 = wellKnownSymbol('species'); + + // `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesCreate = function (originalArray, length) { + var C; + if (isArray(originalArray)) { + C = originalArray.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; + else if (isObject(C)) { + C = C[SPECIES$2]; + if (C === null) C = undefined; + } + } return new (C === undefined ? Array : C)(length === 0 ? 0 : length); + }; + + var SPECIES$1 = wellKnownSymbol('species'); + + var arrayMethodHasSpeciesSupport = function (METHOD_NAME) { + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/677 + return engineV8Version >= 51 || !fails(function () { + var array = []; + var constructor = array.constructor = {}; + constructor[SPECIES$1] = function () { + return { foo: 1 }; + }; + return array[METHOD_NAME](Boolean).foo !== 1; + }); + }; + + var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable'); + var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; + var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded'; + + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/679 + var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () { + var array = []; + array[IS_CONCAT_SPREADABLE] = false; + return array.concat()[0] !== array; + }); + + var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat'); + + var isConcatSpreadable = function (O) { + if (!isObject(O)) return false; + var spreadable = O[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray(O); + }; + + var FORCED = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT; + + // `Array.prototype.concat` method + // https://tc39.es/ecma262/#sec-array.prototype.concat + // with adding support of @@isConcatSpreadable and @@species + _export({ target: 'Array', proto: true, forced: FORCED }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + concat: function concat(arg) { + var O = toObject(this); + var A = arraySpeciesCreate(O, 0); + var n = 0; + var i, k, length, len, E; + for (i = -1, length = arguments.length; i < length; i++) { + E = i === -1 ? O : arguments[i]; + if (isConcatSpreadable(E)) { + len = toLength(E.length); + if (n + len > MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]); + } else { + if (n >= MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + createProperty(A, n++, E); + } + } + A.length = n; + return A; + } + }); + + var aFunction = function (it) { + if (typeof it != 'function') { + throw TypeError(String(it) + ' is not a function'); + } return it; + }; + + // optional / simple context binding + var functionBindContext = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 0: return function () { + return fn.call(that); + }; + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; + }; + + var push = [].push; + + // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation + var createMethod = function (TYPE) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var IS_FILTER_OUT = TYPE == 7; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + return function ($this, callbackfn, that, specificCreate) { + var O = toObject($this); + var self = indexedObject(O); + var boundFunction = functionBindContext(callbackfn, that, 3); + var length = toLength(self.length); + var index = 0; + var create = specificCreate || arraySpeciesCreate; + var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_OUT ? create($this, 0) : undefined; + var value, result; + for (;length > index; index++) if (NO_HOLES || index in self) { + value = self[index]; + result = boundFunction(value, index, O); + if (TYPE) { + if (IS_MAP) target[index] = result; // map + else if (result) switch (TYPE) { + case 3: return true; // some + case 5: return value; // find + case 6: return index; // findIndex + case 2: push.call(target, value); // filter + } else switch (TYPE) { + case 4: return false; // every + case 7: push.call(target, value); // filterOut + } + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target; + }; + }; + + var arrayIteration = { + // `Array.prototype.forEach` method + // https://tc39.es/ecma262/#sec-array.prototype.foreach + forEach: createMethod(0), + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + map: createMethod(1), + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + filter: createMethod(2), + // `Array.prototype.some` method + // https://tc39.es/ecma262/#sec-array.prototype.some + some: createMethod(3), + // `Array.prototype.every` method + // https://tc39.es/ecma262/#sec-array.prototype.every + every: createMethod(4), + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + find: createMethod(5), + // `Array.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-array.prototype.findIndex + findIndex: createMethod(6), + // `Array.prototype.filterOut` method + // https://github.com/tc39/proposal-array-filtering + filterOut: createMethod(7) + }; + + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = objectKeys(Properties); + var length = keys.length; + var index = 0; + var key; + while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]); + return O; + }; + + var html = getBuiltIn('document', 'documentElement'); + + var GT = '>'; + var LT = '<'; + var PROTOTYPE = 'prototype'; + var SCRIPT = 'script'; + var IE_PROTO = sharedKey('IE_PROTO'); + + var EmptyConstructor = function () { /* empty */ }; + + var scriptTag = function (content) { + return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT; + }; + + // Create object with fake `null` prototype: use ActiveX Object with cleared prototype + var NullProtoObjectViaActiveX = function (activeXDocument) { + activeXDocument.write(scriptTag('')); + activeXDocument.close(); + var temp = activeXDocument.parentWindow.Object; + activeXDocument = null; // avoid memory leak + return temp; + }; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var NullProtoObjectViaIFrame = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = documentCreateElement('iframe'); + var JS = 'java' + SCRIPT + ':'; + var iframeDocument; + iframe.style.display = 'none'; + html.appendChild(iframe); + // https://github.com/zloirock/core-js/issues/475 + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag('document.F=Object')); + iframeDocument.close(); + return iframeDocument.F; + }; + + // Check for document.domain and active x support + // No need to use active x approach when document.domain is not set + // see https://github.com/es-shims/es5-shim/issues/150 + // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 + // avoid IE GC bug + var activeXDocument; + var NullProtoObject = function () { + try { + /* global ActiveXObject -- old IE */ + activeXDocument = document.domain && new ActiveXObject('htmlfile'); + } catch (error) { /* ignore */ } + NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame(); + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]]; + return NullProtoObject(); + }; + + hiddenKeys$1[IE_PROTO] = true; + + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + var objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + EmptyConstructor[PROTOTYPE] = anObject(O); + result = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = NullProtoObject(); + return Properties === undefined ? result : objectDefineProperties(result, Properties); + }; + + var UNSCOPABLES = wellKnownSymbol('unscopables'); + var ArrayPrototype = Array.prototype; + + // Array.prototype[@@unscopables] + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + if (ArrayPrototype[UNSCOPABLES] == undefined) { + objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, { + configurable: true, + value: objectCreate(null) + }); + } + + // add a key to Array.prototype[@@unscopables] + var addToUnscopables = function (key) { + ArrayPrototype[UNSCOPABLES][key] = true; + }; + + var $find = arrayIteration.find; + + + var FIND = 'find'; + var SKIPS_HOLES = true; + + // Shouldn't skip holes + if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; }); + + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + _export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables(FIND); + + var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('slice'); + + var SPECIES = wellKnownSymbol('species'); + var nativeSlice = [].slice; + var max = Math.max; + + // `Array.prototype.slice` method + // https://tc39.es/ecma262/#sec-array.prototype.slice + // fallback for not array-like ES3 strings and DOM objects + _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, { + slice: function slice(start, end) { + var O = toIndexedObject(this); + var length = toLength(O.length); + var k = toAbsoluteIndex(start, length); + var fin = toAbsoluteIndex(end === undefined ? length : end, length); + // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible + var Constructor, result, n; + if (isArray(O)) { + Constructor = O.constructor; + // cross-realm fallback + if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) { + Constructor = undefined; + } else if (isObject(Constructor)) { + Constructor = Constructor[SPECIES]; + if (Constructor === null) Constructor = undefined; + } + if (Constructor === Array || Constructor === undefined) { + return nativeSlice.call(O, k, fin); + } + } + result = new (Constructor === undefined ? Array : Constructor)(max(fin - k, 0)); + for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]); + result.length = n; + return result; + } + }); + + /** + * @author: Dustin Utecht + * @github: https://github.com/UtechtDustin + */ + + var Utils = $__default['default'].fn.bootstrapTable.utils; + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, { + customView: false, + showCustomView: false, + showCustomViewButton: false + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults.icons, { + customView: { + bootstrap3: 'glyphicon glyphicon-eye-open', + bootstrap4: 'fa fa-eye', + semantic: 'fa fa-eye', + foundation: 'fa fa-eye', + bulma: 'fa fa-eye', + materialize: 'remove_red_eye' + }[$__default['default'].fn.bootstrapTable.theme] || 'fa-eye' + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, { + onCustomViewPostBody: function onCustomViewPostBody() { + return false; + }, + onCustomViewPreBody: function onCustomViewPreBody() { + return false; + } + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.locales, { + formatToggleCustomView: function formatToggleCustomView() { + return 'Toggle custom view'; + } + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, $__default['default'].fn.bootstrapTable.locales); + $__default['default'].fn.bootstrapTable.methods.push('toggleCustomView'); + $__default['default'].extend($__default['default'].fn.bootstrapTable.Constructor.EVENTS, { + 'custom-view-post-body.bs.table': 'onCustomViewPostBody', + 'custom-view-pre-body.bs.table': 'onCustomViewPreBody' + }); + + $__default['default'].BootstrapTable = /*#__PURE__*/function (_$$BootstrapTable) { + _inherits(_class, _$$BootstrapTable); + + var _super = _createSuper(_class); + + function _class() { + _classCallCheck(this, _class); + + return _super.apply(this, arguments); + } + + _createClass(_class, [{ + key: "init", + value: function init() { + this.showCustomView = this.options.showCustomView; + + _get(_getPrototypeOf(_class.prototype), "init", this).call(this); + } + }, { + key: "initToolbar", + value: function initToolbar() { + var _get2; + + if (this.options.customView && this.options.showCustomViewButton) { + this.buttons = Object.assign(this.buttons, { + customView: { + text: this.options.formatToggleCustomView(), + icon: this.options.icons.customView, + event: this.toggleCustomView, + attributes: { + 'aria-label': this.options.formatToggleCustomView(), + title: this.options.formatToggleCustomView() + } + } + }); + } + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + (_get2 = _get(_getPrototypeOf(_class.prototype), "initToolbar", this)).call.apply(_get2, [this].concat(args)); + } + }, { + key: "initBody", + value: function initBody() { + _get(_getPrototypeOf(_class.prototype), "initBody", this).call(this); + + if (!this.options.customView) { + return; + } + + var $table = this.$el; + var $customViewContainer = this.$container.find('.fixed-table-custom-view'); + $table.hide(); + $customViewContainer.hide(); + + if (!this.options.customView || !this.showCustomView) { + $table.show(); + return; + } + + var data = this.getData().slice(this.pageFrom - 1, this.pageTo); + var value = Utils.calculateObjectValue(this, this.options.customView, [data], ''); + this.trigger('custom-view-pre-body', data, value); + + if ($customViewContainer.length === 1) { + $customViewContainer.show().html(value); + } else { + this.$tableBody.after("
    ".concat(value, "
    ")); + } + + this.trigger('custom-view-post-body', data, value); + } + }, { + key: "toggleCustomView", + value: function toggleCustomView() { + this.showCustomView = !this.showCustomView; + this.initBody(); + } + }]); + + return _class; + }($__default['default'].BootstrapTable); + +}))); diff --git a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js b/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js index a39dddd030..87bef30086 100644 --- a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js +++ b/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js @@ -1,7 +1,10 @@ -/* -* bootstrap-table - v1.12.1 - 2018-03-12 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2018 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";a.fn.bootstrapTable.locales["en-US"]={formatLoadingMessage:function(){return"Loading, please wait..."},formatRecordsPerPage:function(a){return a+" rows per page"},formatShowingRows:function(a,b,c){return"Showing "+a+" to "+b+" of "+c+" rows"},formatSearch:function(){return"Search"},formatNoMatches:function(){return"No matching records found"},formatPaginationSwitch:function(){return"Hide/Show pagination"},formatRefresh:function(){return"Refresh"},formatToggle:function(){return"Toggle"},formatColumns:function(){return"Columns"},formatAllRows:function(){return"All"},formatExport:function(){return"Export data"},formatClearFilters:function(){return"Clear filters"}},a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales["en-US"])}(jQuery); \ No newline at end of file +/** + * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation) + * + * @version v1.18.3 + * @homepage https://bootstrap-table.com + * @author wenzhixin (http://wenzhixin.net.cn/) + * @license MIT + */ + +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).jQuery)}(this,(function(t){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var r=n(t),e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function o(t,n){return t(n={exports:{}},n.exports),n.exports}var i=function(t){return t&&t.Math==Math&&t},u=i("object"==typeof globalThis&&globalThis)||i("object"==typeof window&&window)||i("object"==typeof self&&self)||i("object"==typeof e&&e)||function(){return this}()||Function("return this")(),f=function(t){try{return!!t()}catch(t){return!0}},c=!f((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),a={}.propertyIsEnumerable,l=Object.getOwnPropertyDescriptor,s={f:l&&!a.call({1:2},1)?function(t){var n=l(this,t);return!!n&&n.enumerable}:a},p=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}},g={}.toString,d=function(t){return g.call(t).slice(8,-1)},h="".split,y=f((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==d(t)?h.call(t,""):Object(t)}:Object,m=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t},v=function(t){return y(m(t))},w=function(t){return"object"==typeof t?null!==t:"function"==typeof t},b=function(t,n){if(!w(t))return t;var r,e;if(n&&"function"==typeof(r=t.toString)&&!w(e=r.call(t)))return e;if("function"==typeof(r=t.valueOf)&&!w(e=r.call(t)))return e;if(!n&&"function"==typeof(r=t.toString)&&!w(e=r.call(t)))return e;throw TypeError("Can't convert object to primitive value")},S={}.hasOwnProperty,T=function(t,n){return S.call(t,n)},O=u.document,P=w(O)&&w(O.createElement),j=!c&&!f((function(){return 7!=Object.defineProperty((t="div",P?O.createElement(t):{}),"a",{get:function(){return 7}}).a;var t})),x=Object.getOwnPropertyDescriptor,A={f:c?x:function(t,n){if(t=v(t),n=b(n,!0),j)try{return x(t,n)}catch(t){}if(T(t,n))return p(!s.f.call(t,n),t[n])}},C=function(t){if(!w(t))throw TypeError(String(t)+" is not an object");return t},E=Object.defineProperty,M={f:c?E:function(t,n,r){if(C(t),n=b(n,!0),C(r),j)try{return E(t,n,r)}catch(t){}if("get"in r||"set"in r)throw TypeError("Accessors not supported");return"value"in r&&(t[n]=r.value),t}},R=c?function(t,n,r){return M.f(t,n,p(1,r))}:function(t,n,r){return t[n]=r,t},F=function(t,n){try{R(u,t,n)}catch(r){u[t]=n}return n},N="__core-js_shared__",L=u[N]||F(N,{}),k=Function.toString;"function"!=typeof L.inspectSource&&(L.inspectSource=function(t){return k.call(t)});var H,I,_,D,q=L.inspectSource,z=u.WeakMap,G="function"==typeof z&&/native code/.test(q(z)),U=o((function(t){(t.exports=function(t,n){return L[t]||(L[t]=void 0!==n?n:{})})("versions",[]).push({version:"3.9.1",mode:"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})})),B=0,W=Math.random(),J=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++B+W).toString(36)},K=U("keys"),Q={},V=u.WeakMap;if(G){var Y=L.state||(L.state=new V),X=Y.get,Z=Y.has,$=Y.set;H=function(t,n){return n.facade=t,$.call(Y,t,n),n},I=function(t){return X.call(Y,t)||{}},_=function(t){return Z.call(Y,t)}}else{var tt=K[D="state"]||(K[D]=J(D));Q[tt]=!0,H=function(t,n){return n.facade=t,R(t,tt,n),n},I=function(t){return T(t,tt)?t[tt]:{}},_=function(t){return T(t,tt)}}var nt,rt,et={set:H,get:I,has:_,enforce:function(t){return _(t)?I(t):H(t,{})},getterFor:function(t){return function(n){var r;if(!w(n)||(r=I(n)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return r}}},ot=o((function(t){var n=et.get,r=et.enforce,e=String(String).split("String");(t.exports=function(t,n,o,i){var f,c=!!i&&!!i.unsafe,a=!!i&&!!i.enumerable,l=!!i&&!!i.noTargetGet;"function"==typeof o&&("string"!=typeof n||T(o,"name")||R(o,"name",n),(f=r(o)).source||(f.source=e.join("string"==typeof n?n:""))),t!==u?(c?!l&&t[n]&&(a=!0):delete t[n],a?t[n]=o:R(t,n,o)):a?t[n]=o:F(n,o)})(Function.prototype,"toString",(function(){return"function"==typeof this&&n(this).source||q(this)}))})),it=u,ut=function(t){return"function"==typeof t?t:void 0},ft=function(t,n){return arguments.length<2?ut(it[t])||ut(u[t]):it[t]&&it[t][n]||u[t]&&u[t][n]},ct=Math.ceil,at=Math.floor,lt=function(t){return isNaN(t=+t)?0:(t>0?at:ct)(t)},st=Math.min,pt=function(t){return t>0?st(lt(t),9007199254740991):0},gt=Math.max,dt=Math.min,ht=function(t){return function(n,r,e){var o,i=v(n),u=pt(i.length),f=function(t,n){var r=lt(t);return r<0?gt(r+n,0):dt(r,n)}(e,u);if(t&&r!=r){for(;u>f;)if((o=i[f++])!=o)return!0}else for(;u>f;f++)if((t||f in i)&&i[f]===r)return t||f||0;return!t&&-1}},yt={includes:ht(!0),indexOf:ht(!1)}.indexOf,mt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"].concat("length","prototype"),vt={f:Object.getOwnPropertyNames||function(t){return function(t,n){var r,e=v(t),o=0,i=[];for(r in e)!T(Q,r)&&T(e,r)&&i.push(r);for(;n.length>o;)T(e,r=n[o++])&&(~yt(i,r)||i.push(r));return i}(t,mt)}},wt={f:Object.getOwnPropertySymbols},bt=ft("Reflect","ownKeys")||function(t){var n=vt.f(C(t)),r=wt.f;return r?n.concat(r(t)):n},St=function(t,n){for(var r=bt(n),e=M.f,o=A.f,i=0;i=74)&&(nt=Lt.match(/Chrome\/(\d+)/))&&(rt=nt[1]);var _t,Dt=rt&&+rt,qt=!!Object.getOwnPropertySymbols&&!f((function(){return!Symbol.sham&&(Nt?38===Dt:Dt>37&&Dt<41)})),zt=qt&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,Gt=U("wks"),Ut=u.Symbol,Bt=zt?Ut:Ut&&Ut.withoutSetter||J,Wt=function(t){return T(Gt,t)&&(qt||"string"==typeof Gt[t])||(qt&&T(Ut,t)?Gt[t]=Ut[t]:Gt[t]=Bt("Symbol."+t)),Gt[t]},Jt=Wt("species"),Kt=function(t,n){var r;return Mt(t)&&("function"!=typeof(r=t.constructor)||r!==Array&&!Mt(r.prototype)?w(r)&&null===(r=r[Jt])&&(r=void 0):r=void 0),new(void 0===r?Array:r)(0===n?0:n)},Qt=Wt("species"),Vt=Wt("isConcatSpreadable"),Yt=9007199254740991,Xt="Maximum allowed index exceeded",Zt=Dt>=51||!f((function(){var t=[];return t[Vt]=!1,t.concat()[0]!==t})),$t=(_t="concat",Dt>=51||!f((function(){var t=[];return(t.constructor={})[Qt]=function(){return{foo:1}},1!==t[_t](Boolean).foo}))),tn=function(t){if(!w(t))return!1;var n=t[Vt];return void 0!==n?!!n:Mt(t)};!function(t,n){var r,e,o,i,f,c=t.target,a=t.global,l=t.stat;if(r=a?u:l?u[c]||F(c,{}):(u[c]||{}).prototype)for(e in n){if(i=n[e],o=t.noTargetGet?(f=Et(r,e))&&f.value:r[e],!Ct(a?e:c+(l?".":"#")+e,t.forced)&&void 0!==o){if(typeof i==typeof o)continue;St(i,o)}(t.sham||o&&o.sham)&&R(i,"sham",!0),ot(r,e,i,t)}}({target:"Array",proto:!0,forced:!Zt||!$t},{concat:function(t){var n,r,e,o,i,u=Rt(this),f=Kt(u,0),c=0;for(n=-1,e=arguments.length;nYt)throw TypeError(Xt);for(r=0;r=Yt)throw TypeError(Xt);Ft(f,c++,i)}return f.length=c,f}}),r.default.fn.bootstrapTable.locales["en-US"]=r.default.fn.bootstrapTable.locales.en={formatCopyRows:function(){return"Copy Rows"},formatPrint:function(){return"Print"},formatLoadingMessage:function(){return"Loading, please wait"},formatRecordsPerPage:function(t){return"".concat(t," rows per page")},formatShowingRows:function(t,n,r,e){return void 0!==e&&e>0&&e>r?"Showing ".concat(t," to ").concat(n," of ").concat(r," rows (filtered from ").concat(e," total rows)"):"Showing ".concat(t," to ").concat(n," of ").concat(r," rows")},formatSRPaginationPreText:function(){return"previous page"},formatSRPaginationPageText:function(t){return"to page ".concat(t)},formatSRPaginationNextText:function(){return"next page"},formatDetailPagination:function(t){return"Showing ".concat(t," rows")},formatClearSearch:function(){return"Clear Search"},formatSearch:function(){return"Search"},formatNoMatches:function(){return"No matching records found"},formatPaginationSwitch:function(){return"Hide/Show pagination"},formatPaginationSwitchDown:function(){return"Show pagination"},formatPaginationSwitchUp:function(){return"Hide pagination"},formatRefresh:function(){return"Refresh"},formatToggle:function(){return"Toggle"},formatToggleOn:function(){return"Show card view"},formatToggleOff:function(){return"Hide card view"},formatColumns:function(){return"Columns"},formatColumnsToggleAll:function(){return"Toggle all"},formatFullscreen:function(){return"Fullscreen"},formatAllRows:function(){return"All"},formatAutoRefresh:function(){return"Auto Refresh"},formatExport:function(){return"Export data"},formatJumpTo:function(){return"GO"},formatAdvancedSearch:function(){return"Advanced search"},formatAdvancedCloseButton:function(){return"Close"},formatFilterControlSwitch:function(){return"Hide/Show controls"},formatFilterControlSwitchHide:function(){return"Hide controls"},formatFilterControlSwitchShow:function(){return"Show controls"}},r.default.extend(r.default.fn.bootstrapTable.defaults,r.default.fn.bootstrapTable.locales["en-US"])})); diff --git a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js b/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js index 5fdfd2ee58..941ec06bfa 100644 --- a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js +++ b/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js @@ -1,17 +1,28 @@ (function (global, factory) { - if (typeof define === "function" && define.amd) { - define([], factory); - } else if (typeof exports !== "undefined") { - factory(); - } else { - var mod = { - exports: {} - }; - factory(); - global.bootstrapTable = mod.exports; + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : + typeof define === 'function' && define.amd ? define(['jquery'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.BootstrapTable = factory(global.jQuery)); +}(this, (function ($) { 'use strict'; + + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + + var $__default = /*#__PURE__*/_interopDefaultLegacy($); + + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); } -})(this, function () { - 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { @@ -19,2634 +30,6084 @@ } } - var _createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var _slicedToArray = function () { - function sliceIterator(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"]) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; - } - - return function (arr, i) { - if (Array.isArray(arr)) { - return arr; - } else if (Symbol.iterator in Object(arr)) { - return sliceIterator(arr, i); - } else { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - }; - }(); - - function _toConsumableArray(arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { - arr2[i] = arr[i]; - } - - return arr2; - } else { - return Array.from(arr); + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); } } - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } - /** - * @author zhixin wen - * version: 1.14.2 - * https://github.com/wenzhixin/bootstrap-table/ - */ + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } - (function ($) { - // TOOLS DEFINITION - // ====================== + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; - var bootstrapVersion = 4; try { - var rawVersion = $.fn.dropdown.Constructor.VERSION; + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); - // Only try to parse VERSION if is is defined. - // It is undefined in older versions of Bootstrap (tested with 3.1.1). - if (rawVersion !== undefined) { - bootstrapVersion = parseInt(rawVersion, 10); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; } - } catch (e) { - // ignore } - var constants = { - 3: { - theme: 'bootstrap3', - iconsPrefix: 'glyphicon', - icons: { - paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', - paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', - refresh: 'glyphicon-refresh icon-refresh', - toggleOff: 'glyphicon-list-alt icon-list-alt', - toggleOn: 'glyphicon-list-alt icon-list-alt', - columns: 'glyphicon-th icon-th', - detailOpen: 'glyphicon-plus icon-plus', - detailClose: 'glyphicon-minus icon-minus', - fullscreen: 'glyphicon-fullscreen' - }, - classes: { - buttonsPrefix: 'btn', - buttons: 'default', - buttonsGroup: 'btn-group', - buttonsDropdown: 'btn-group', - pull: 'pull', - inputGroup: '', - input: 'form-control', - paginationDropdown: 'btn-group dropdown', - dropup: 'dropup', - dropdownActive: 'active', - paginationActive: 'active' - }, - html: { - toobarDropdow: [''], - toobarDropdowItem: '
  • ', - pageDropdown: [''], - pageDropdownItem: '', - dropdownCaret: '', - pagination: ['
      ', '
    '], - paginationItem: '
  • %s
  • ', - icon: '' - } - }, - 4: { - theme: 'bootstrap4', - iconsPrefix: 'fa', - icons: { - paginationSwitchDown: 'fa-caret-square-down', - paginationSwitchUp: 'fa-caret-square-up', - refresh: 'fa-sync', - toggleOff: 'fa-toggle-off', - toggleOn: 'fa-toggle-on', - columns: 'fa-th-list', - fullscreen: 'fa-arrows-alt', - detailOpen: 'fa-plus', - detailClose: 'fa-minus' - }, - classes: { - buttonsPrefix: 'btn', - buttons: 'secondary', - buttonsGroup: 'btn-group', - buttonsDropdown: 'btn-group', - pull: 'float', - inputGroup: '', - input: 'form-control', - paginationDropdown: 'btn-group dropdown', - dropup: 'dropup', - dropdownActive: 'active', - paginationActive: 'active' - }, - html: { - toobarDropdow: [''], - toobarDropdowItem: '', - pageDropdown: [''], - pageDropdownItem: '%s', - dropdownCaret: '', - pagination: ['
      ', '
    '], - paginationItem: '
  • %s
  • ', - icon: '' - } - } - }[bootstrapVersion]; + return _arr; + } - var Utils = { - bootstrapVersion: bootstrapVersion, + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } - sprintf: function sprintf(_str) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; - var flag = true; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _createForOfIteratorHelper(o, allowArrayLike) { + var it; + + if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { + if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { + if (it) o = it; var i = 0; - var str = _str.replace(/%s/g, function () { - var arg = args[i++]; + var F = function () {}; - if (typeof arg === 'undefined') { - flag = false; - return ''; + return { + s: F, + n: function () { + if (i >= o.length) return { + done: true + }; + return { + done: false, + value: o[i++] + }; + }, + e: function (e) { + throw e; + }, + f: F + }; + } + + throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var normalCompletion = true, + didErr = false, + err; + return { + s: function () { + it = o[Symbol.iterator](); + }, + n: function () { + var step = it.next(); + normalCompletion = step.done; + return step; + }, + e: function (e) { + didErr = true; + err = e; + }, + f: function () { + try { + if (!normalCompletion && it.return != null) it.return(); + } finally { + if (didErr) throw err; + } + } + }; + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var check = function (it) { + return it && it.Math == Math && it; + }; + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global_1 = + /* global globalThis -- safe */ + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof commonjsGlobal == 'object' && commonjsGlobal) || + // eslint-disable-next-line no-new-func -- fallback + (function () { return this; })() || Function('return this')(); + + var fails = function (exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + + // Detect IE8's incomplete defineProperty implementation + var descriptors = !fails(function () { + return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; + }); + + var nativePropertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor$4 = Object.getOwnPropertyDescriptor; + + // Nashorn ~ JDK8 bug + var NASHORN_BUG = getOwnPropertyDescriptor$4 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1); + + // `Object.prototype.propertyIsEnumerable` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable + var f$4 = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor$4(this, V); + return !!descriptor && descriptor.enumerable; + } : nativePropertyIsEnumerable; + + var objectPropertyIsEnumerable = { + f: f$4 + }; + + var createPropertyDescriptor = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + + var toString = {}.toString; + + var classofRaw = function (it) { + return toString.call(it).slice(8, -1); + }; + + var split = ''.split; + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var indexedObject = fails(function () { + // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 + // eslint-disable-next-line no-prototype-builtins -- safe + return !Object('z').propertyIsEnumerable(0); + }) ? function (it) { + return classofRaw(it) == 'String' ? split.call(it, '') : Object(it); + } : Object; + + // `RequireObjectCoercible` abstract operation + // https://tc39.es/ecma262/#sec-requireobjectcoercible + var requireObjectCoercible = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; + }; + + // toObject with fallback for non-array-like ES3 strings + + + + var toIndexedObject = function (it) { + return indexedObject(requireObjectCoercible(it)); + }; + + var isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; + + // `ToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-toprimitive + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + var toPrimitive = function (input, PREFERRED_STRING) { + if (!isObject(input)) return input; + var fn, val; + if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; + if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + throw TypeError("Can't convert object to primitive value"); + }; + + var hasOwnProperty = {}.hasOwnProperty; + + var has$1 = function (it, key) { + return hasOwnProperty.call(it, key); + }; + + var document$1 = global_1.document; + // typeof document.createElement is 'object' in old IE + var EXISTS = isObject(document$1) && isObject(document$1.createElement); + + var documentCreateElement = function (it) { + return EXISTS ? document$1.createElement(it) : {}; + }; + + // Thank's IE8 for his funny defineProperty + var ie8DomDefine = !descriptors && !fails(function () { + return Object.defineProperty(documentCreateElement('div'), 'a', { + get: function () { return 7; } + }).a != 7; + }); + + var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + var f$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject(O); + P = toPrimitive(P, true); + if (ie8DomDefine) try { + return nativeGetOwnPropertyDescriptor(O, P); + } catch (error) { /* empty */ } + if (has$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]); + }; + + var objectGetOwnPropertyDescriptor = { + f: f$3 + }; + + var anObject = function (it) { + if (!isObject(it)) { + throw TypeError(String(it) + ' is not an object'); + } return it; + }; + + var nativeDefineProperty = Object.defineProperty; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (ie8DomDefine) try { + return nativeDefineProperty(O, P, Attributes); + } catch (error) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + + var objectDefineProperty = { + f: f$2 + }; + + var createNonEnumerableProperty = descriptors ? function (object, key, value) { + return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + + var setGlobal = function (key, value) { + try { + createNonEnumerableProperty(global_1, key, value); + } catch (error) { + global_1[key] = value; + } return value; + }; + + var SHARED = '__core-js_shared__'; + var store$1 = global_1[SHARED] || setGlobal(SHARED, {}); + + var sharedStore = store$1; + + var functionToString = Function.toString; + + // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper + if (typeof sharedStore.inspectSource != 'function') { + sharedStore.inspectSource = function (it) { + return functionToString.call(it); + }; + } + + var inspectSource = sharedStore.inspectSource; + + var WeakMap$1 = global_1.WeakMap; + + var nativeWeakMap = typeof WeakMap$1 === 'function' && /native code/.test(inspectSource(WeakMap$1)); + + var shared = createCommonjsModule(function (module) { + (module.exports = function (key, value) { + return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: '3.9.1', + mode: 'global', + copyright: '© 2021 Denis Pushkarev (zloirock.ru)' + }); + }); + + var id = 0; + var postfix = Math.random(); + + var uid = function (key) { + return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36); + }; + + var keys$2 = shared('keys'); + + var sharedKey = function (key) { + return keys$2[key] || (keys$2[key] = uid(key)); + }; + + var hiddenKeys$1 = {}; + + var WeakMap = global_1.WeakMap; + var set, get, has; + + var enforce = function (it) { + return has(it) ? get(it) : set(it, {}); + }; + + var getterFor = function (TYPE) { + return function (it) { + var state; + if (!isObject(it) || (state = get(it)).type !== TYPE) { + throw TypeError('Incompatible receiver, ' + TYPE + ' required'); + } return state; + }; + }; + + if (nativeWeakMap) { + var store = sharedStore.state || (sharedStore.state = new WeakMap()); + var wmget = store.get; + var wmhas = store.has; + var wmset = store.set; + set = function (it, metadata) { + metadata.facade = it; + wmset.call(store, it, metadata); + return metadata; + }; + get = function (it) { + return wmget.call(store, it) || {}; + }; + has = function (it) { + return wmhas.call(store, it); + }; + } else { + var STATE = sharedKey('state'); + hiddenKeys$1[STATE] = true; + set = function (it, metadata) { + metadata.facade = it; + createNonEnumerableProperty(it, STATE, metadata); + return metadata; + }; + get = function (it) { + return has$1(it, STATE) ? it[STATE] : {}; + }; + has = function (it) { + return has$1(it, STATE); + }; + } + + var internalState = { + set: set, + get: get, + has: has, + enforce: enforce, + getterFor: getterFor + }; + + var redefine = createCommonjsModule(function (module) { + var getInternalState = internalState.get; + var enforceInternalState = internalState.enforce; + var TEMPLATE = String(String).split('String'); + + (module.exports = function (O, key, value, options) { + var unsafe = options ? !!options.unsafe : false; + var simple = options ? !!options.enumerable : false; + var noTargetGet = options ? !!options.noTargetGet : false; + var state; + if (typeof value == 'function') { + if (typeof key == 'string' && !has$1(value, 'name')) { + createNonEnumerableProperty(value, 'name', key); + } + state = enforceInternalState(value); + if (!state.source) { + state.source = TEMPLATE.join(typeof key == 'string' ? key : ''); + } + } + if (O === global_1) { + if (simple) O[key] = value; + else setGlobal(key, value); + return; + } else if (!unsafe) { + delete O[key]; + } else if (!noTargetGet && O[key]) { + simple = true; + } + if (simple) O[key] = value; + else createNonEnumerableProperty(O, key, value); + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + })(Function.prototype, 'toString', function toString() { + return typeof this == 'function' && getInternalState(this).source || inspectSource(this); + }); + }); + + var path = global_1; + + var aFunction$1 = function (variable) { + return typeof variable == 'function' ? variable : undefined; + }; + + var getBuiltIn = function (namespace, method) { + return arguments.length < 2 ? aFunction$1(path[namespace]) || aFunction$1(global_1[namespace]) + : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; + }; + + var ceil = Math.ceil; + var floor$1 = Math.floor; + + // `ToInteger` abstract operation + // https://tc39.es/ecma262/#sec-tointeger + var toInteger = function (argument) { + return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor$1 : ceil)(argument); + }; + + var min$6 = Math.min; + + // `ToLength` abstract operation + // https://tc39.es/ecma262/#sec-tolength + var toLength = function (argument) { + return argument > 0 ? min$6(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 + }; + + var max$3 = Math.max; + var min$5 = Math.min; + + // Helper for a popular repeating case of the spec: + // Let integer be ? ToInteger(index). + // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). + var toAbsoluteIndex = function (index, length) { + var integer = toInteger(index); + return integer < 0 ? max$3(integer + length, 0) : min$5(integer, length); + }; + + // `Array.prototype.{ indexOf, includes }` methods implementation + var createMethod$4 = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare -- NaN check + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare -- NaN check + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + + var arrayIncludes = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod$4(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod$4(false) + }; + + var indexOf = arrayIncludes.indexOf; + + + var objectKeysInternal = function (object, names) { + var O = toIndexedObject(object); + var i = 0; + var result = []; + var key; + for (key in O) !has$1(hiddenKeys$1, key) && has$1(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has$1(O, key = names[i++])) { + ~indexOf(result, key) || result.push(key); + } + return result; + }; + + // IE8- don't enum bug keys + var enumBugKeys = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + var hiddenKeys = enumBugKeys.concat('length', 'prototype'); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return objectKeysInternal(O, hiddenKeys); + }; + + var objectGetOwnPropertyNames = { + f: f$1 + }; + + var f = Object.getOwnPropertySymbols; + + var objectGetOwnPropertySymbols = { + f: f + }; + + // all object keys, includes non-enumerable and symbols + var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { + var keys = objectGetOwnPropertyNames.f(anObject(it)); + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys; + }; + + var copyConstructorProperties = function (target, source) { + var keys = ownKeys(source); + var defineProperty = objectDefineProperty.f; + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!has$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + }; + + var replacement = /#|\.prototype\./; + + var isForced = function (feature, detection) { + var value = data[normalize(feature)]; + return value == POLYFILL ? true + : value == NATIVE ? false + : typeof detection == 'function' ? fails(detection) + : !!detection; + }; + + var normalize = isForced.normalize = function (string) { + return String(string).replace(replacement, '.').toLowerCase(); + }; + + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = 'N'; + var POLYFILL = isForced.POLYFILL = 'P'; + + var isForced_1 = isForced; + + var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f; + + + + + + + /* + options.target - name of the target object + options.global - target is the global object + options.stat - export as static methods of target + options.proto - export as prototype methods of target + options.real - real prototype method for the `pure` version + options.forced - export even if the native feature is available + options.bind - bind methods to the target, required for the `pure` version + options.wrap - wrap constructors to preventing global pollution, required for the `pure` version + options.unsafe - use the simple assignment of property instead of delete + defineProperty + options.sham - add a flag to not completely full polyfills + options.enumerable - export as enumerable property + options.noTargetGet - prevent calling a getter on target + */ + var _export = function (options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = global_1; + } else if (STATIC) { + target = global_1[TARGET] || setGlobal(TARGET, {}); + } else { + target = (global_1[TARGET] || {}).prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.noTargetGet) { + descriptor = getOwnPropertyDescriptor$3(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); + // contained in target + if (!FORCED && targetProperty !== undefined) { + if (typeof sourceProperty === typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + // add a flag to not completely full polyfills + if (options.sham || (targetProperty && targetProperty.sham)) { + createNonEnumerableProperty(sourceProperty, 'sham', true); + } + // extend global + redefine(target, key, sourceProperty, options); + } + }; + + // a string of all valid unicode whitespaces + var whitespaces = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' + + '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; + + var whitespace = '[' + whitespaces + ']'; + var ltrim = RegExp('^' + whitespace + whitespace + '*'); + var rtrim = RegExp(whitespace + whitespace + '*$'); + + // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation + var createMethod$3 = function (TYPE) { + return function ($this) { + var string = String(requireObjectCoercible($this)); + if (TYPE & 1) string = string.replace(ltrim, ''); + if (TYPE & 2) string = string.replace(rtrim, ''); + return string; + }; + }; + + var stringTrim = { + // `String.prototype.{ trimLeft, trimStart }` methods + // https://tc39.es/ecma262/#sec-string.prototype.trimstart + start: createMethod$3(1), + // `String.prototype.{ trimRight, trimEnd }` methods + // https://tc39.es/ecma262/#sec-string.prototype.trimend + end: createMethod$3(2), + // `String.prototype.trim` method + // https://tc39.es/ecma262/#sec-string.prototype.trim + trim: createMethod$3(3) + }; + + var non = '\u200B\u0085\u180E'; + + // check that a method works with the correct list + // of whitespaces and has a correct name + var stringTrimForced = function (METHOD_NAME) { + return fails(function () { + return !!whitespaces[METHOD_NAME]() || non[METHOD_NAME]() != non || whitespaces[METHOD_NAME].name !== METHOD_NAME; + }); + }; + + var $trim = stringTrim.trim; + + + // `String.prototype.trim` method + // https://tc39.es/ecma262/#sec-string.prototype.trim + _export({ target: 'String', proto: true, forced: stringTrimForced('trim') }, { + trim: function trim() { + return $trim(this); + } + }); + + var arrayMethodIsStrict = function (METHOD_NAME, argument) { + var method = [][METHOD_NAME]; + return !!method && fails(function () { + // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing + method.call(null, argument || function () { throw 1; }, 1); + }); + }; + + var nativeJoin = [].join; + + var ES3_STRINGS = indexedObject != Object; + var STRICT_METHOD$3 = arrayMethodIsStrict('join', ','); + + // `Array.prototype.join` method + // https://tc39.es/ecma262/#sec-array.prototype.join + _export({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD$3 }, { + join: function join(separator) { + return nativeJoin.call(toIndexedObject(this), separator === undefined ? ',' : separator); + } + }); + + // `RegExp.prototype.flags` getter implementation + // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags + var regexpFlags = function () { + var that = anObject(this); + var result = ''; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.dotAll) result += 's'; + if (that.unicode) result += 'u'; + if (that.sticky) result += 'y'; + return result; + }; + + // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError, + // so we use an intermediate function. + function RE(s, f) { + return RegExp(s, f); + } + + var UNSUPPORTED_Y$2 = fails(function () { + // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError + var re = RE('a', 'y'); + re.lastIndex = 2; + return re.exec('abcd') != null; + }); + + var BROKEN_CARET = fails(function () { + // https://bugzilla.mozilla.org/show_bug.cgi?id=773687 + var re = RE('^r', 'gy'); + re.lastIndex = 2; + return re.exec('str') != null; + }); + + var regexpStickyHelpers = { + UNSUPPORTED_Y: UNSUPPORTED_Y$2, + BROKEN_CARET: BROKEN_CARET + }; + + var nativeExec = RegExp.prototype.exec; + // This always refers to the native implementation, because the + // String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js, + // which loads this file before patching the method. + var nativeReplace = String.prototype.replace; + + var patchedExec = nativeExec; + + var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/; + var re2 = /b*/g; + nativeExec.call(re1, 'a'); + nativeExec.call(re2, 'a'); + return re1.lastIndex !== 0 || re2.lastIndex !== 0; + })(); + + var UNSUPPORTED_Y$1 = regexpStickyHelpers.UNSUPPORTED_Y || regexpStickyHelpers.BROKEN_CARET; + + // nonparticipating capturing group, copied from es5-shim's String#split patch. + // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing + var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + + var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$1; + + if (PATCH) { + patchedExec = function exec(str) { + var re = this; + var lastIndex, reCopy, match, i; + var sticky = UNSUPPORTED_Y$1 && re.sticky; + var flags = regexpFlags.call(re); + var source = re.source; + var charsAdded = 0; + var strCopy = str; + + if (sticky) { + flags = flags.replace('y', ''); + if (flags.indexOf('g') === -1) { + flags += 'g'; + } + + strCopy = String(str).slice(re.lastIndex); + // Support anchored sticky behavior. + if (re.lastIndex > 0 && (!re.multiline || re.multiline && str[re.lastIndex - 1] !== '\n')) { + source = '(?: ' + source + ')'; + strCopy = ' ' + strCopy; + charsAdded++; + } + // ^(? + rx + ) is needed, in combination with some str slicing, to + // simulate the 'y' flag. + reCopy = new RegExp('^(?:' + source + ')', flags); + } + + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + source + '$(?!\\s)', flags); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex; + + match = nativeExec.call(sticky ? reCopy : re, strCopy); + + if (sticky) { + if (match) { + match.input = match.input.slice(charsAdded); + match[0] = match[0].slice(charsAdded); + match.index = re.lastIndex; + re.lastIndex += match[0].length; + } else re.lastIndex = 0; + } else if (UPDATES_LAST_INDEX_WRONG && match) { + re.lastIndex = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/ + nativeReplace.call(match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; } - return arg; }); - return flag ? str : ''; - }, - isEmptyObject: function isEmptyObject() { - var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + } - return function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(obj).length === 0 && obj.constructor === Object; - }, - isNumeric: function isNumeric(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - }, - getFieldTitle: function getFieldTitle(list, value) { - for (var _iterator = list, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { - var _ref; + return match; + }; + } - if (_isArray) { - if (_i >= _iterator.length) break; - _ref = _iterator[_i++]; - } else { - _i = _iterator.next(); - if (_i.done) break; - _ref = _i.value; + var regexpExec = patchedExec; + + // `RegExp.prototype.exec` method + // https://tc39.es/ecma262/#sec-regexp.prototype.exec + _export({ target: 'RegExp', proto: true, forced: /./.exec !== regexpExec }, { + exec: regexpExec + }); + + var engineIsNode = classofRaw(global_1.process) == 'process'; + + var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; + + var process = global_1.process; + var versions = process && process.versions; + var v8 = versions && versions.v8; + var match, version; + + if (v8) { + match = v8.split('.'); + version = match[0] + match[1]; + } else if (engineUserAgent) { + match = engineUserAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = engineUserAgent.match(/Chrome\/(\d+)/); + if (match) version = match[1]; + } + } + + var engineV8Version = version && +version; + + var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { + /* global Symbol -- required for testing */ + return !Symbol.sham && + // Chrome 38 Symbol has incorrect toString conversion + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41); + }); + + var useSymbolAsUid = nativeSymbol + /* global Symbol -- safe */ + && !Symbol.sham + && typeof Symbol.iterator == 'symbol'; + + var WellKnownSymbolsStore = shared('wks'); + var Symbol$1 = global_1.Symbol; + var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; + + var wellKnownSymbol = function (name) { + if (!has$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { + if (nativeSymbol && has$1(Symbol$1, name)) { + WellKnownSymbolsStore[name] = Symbol$1[name]; + } else { + WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + } + } return WellKnownSymbolsStore[name]; + }; + + // TODO: Remove from `core-js@4` since it's moved to entry points + + + + + + + + var SPECIES$5 = wellKnownSymbol('species'); + + var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () { + // #replace needs built-in support for named groups. + // #match works fine because it just return the exec results, even if it has + // a "grops" property. + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + return ''.replace(re, '$') !== '7'; + }); + + // IE <= 11 replaces $0 with the whole match, as if it was $& + // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0 + var REPLACE_KEEPS_$0 = (function () { + return 'a'.replace(/./, '$0') === '$0'; + })(); + + var REPLACE = wellKnownSymbol('replace'); + // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string + var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () { + if (/./[REPLACE]) { + return /./[REPLACE]('a', '$0') === ''; + } + return false; + })(); + + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + // Weex JS has frozen built-in prototypes, so use try / catch wrapper + var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () { + // eslint-disable-next-line regexp/no-empty-group -- required for testing + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b'; + }); + + var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) { + var SYMBOL = wellKnownSymbol(KEY); + + var DELEGATES_TO_SYMBOL = !fails(function () { + // String methods call symbol-named RegEp methods + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) != 7; + }); + + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + + if (KEY === 'split') { + // We can't use real regex here since it causes deoptimization + // and serious performance degradation in V8 + // https://github.com/zloirock/core-js/issues/306 + re = {}; + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES$5] = function () { return re; }; + re.flags = ''; + re[SYMBOL] = /./[SYMBOL]; + } + + re.exec = function () { execCalled = true; return null; }; + + re[SYMBOL](''); + return !execCalled; + }); + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + (KEY === 'replace' && !( + REPLACE_SUPPORTS_NAMED_GROUPS && + REPLACE_KEEPS_$0 && + !REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE + )) || + (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) + ) { + var nativeRegExpMethod = /./[SYMBOL]; + var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) { + if (regexp.exec === regexpExec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) }; } + return { done: true, value: nativeMethod.call(str, regexp, arg2) }; + } + return { done: false }; + }, { + REPLACE_KEEPS_$0: REPLACE_KEEPS_$0, + REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE: REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE + }); + var stringMethod = methods[0]; + var regexMethod = methods[1]; - var item = _ref; + redefine(String.prototype, KEY, stringMethod); + redefine(RegExp.prototype, SYMBOL, length == 2 + // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) + // 21.2.5.11 RegExp.prototype[@@split](string, limit) + ? function (string, arg) { return regexMethod.call(string, this, arg); } + // 21.2.5.6 RegExp.prototype[@@match](string) + // 21.2.5.9 RegExp.prototype[@@search](string) + : function (string) { return regexMethod.call(string, this); } + ); + } + + if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true); + }; + + var MATCH$2 = wellKnownSymbol('match'); + + // `IsRegExp` abstract operation + // https://tc39.es/ecma262/#sec-isregexp + var isRegexp = function (it) { + var isRegExp; + return isObject(it) && ((isRegExp = it[MATCH$2]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp'); + }; + + var aFunction = function (it) { + if (typeof it != 'function') { + throw TypeError(String(it) + ' is not a function'); + } return it; + }; + + var SPECIES$4 = wellKnownSymbol('species'); + + // `SpeciesConstructor` abstract operation + // https://tc39.es/ecma262/#sec-speciesconstructor + var speciesConstructor = function (O, defaultConstructor) { + var C = anObject(O).constructor; + var S; + return C === undefined || (S = anObject(C)[SPECIES$4]) == undefined ? defaultConstructor : aFunction(S); + }; + + // `String.prototype.{ codePointAt, at }` methods implementation + var createMethod$2 = function (CONVERT_TO_STRING) { + return function ($this, pos) { + var S = String(requireObjectCoercible($this)); + var position = toInteger(pos); + var size = S.length; + var first, second; + if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined; + first = S.charCodeAt(position); + return first < 0xD800 || first > 0xDBFF || position + 1 === size + || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF + ? CONVERT_TO_STRING ? S.charAt(position) : first + : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000; + }; + }; + + var stringMultibyte = { + // `String.prototype.codePointAt` method + // https://tc39.es/ecma262/#sec-string.prototype.codepointat + codeAt: createMethod$2(false), + // `String.prototype.at` method + // https://github.com/mathiasbynens/String.prototype.at + charAt: createMethod$2(true) + }; + + var charAt = stringMultibyte.charAt; + + // `AdvanceStringIndex` abstract operation + // https://tc39.es/ecma262/#sec-advancestringindex + var advanceStringIndex = function (S, index, unicode) { + return index + (unicode ? charAt(S, index).length : 1); + }; + + // `RegExpExec` abstract operation + // https://tc39.es/ecma262/#sec-regexpexec + var regexpExecAbstract = function (R, S) { + var exec = R.exec; + if (typeof exec === 'function') { + var result = exec.call(R, S); + if (typeof result !== 'object') { + throw TypeError('RegExp exec method returned something other than an Object or null'); + } + return result; + } + + if (classofRaw(R) !== 'RegExp') { + throw TypeError('RegExp#exec called on incompatible receiver'); + } + + return regexpExec.call(R, S); + }; + + var arrayPush = [].push; + var min$4 = Math.min; + var MAX_UINT32 = 0xFFFFFFFF; + + // babel-minify transpiles RegExp('x', 'y') -> /x/y and it causes SyntaxError + var SUPPORTS_Y = !fails(function () { return !RegExp(MAX_UINT32, 'y'); }); + + // @@split logic + fixRegexpWellKnownSymbolLogic('split', 2, function (SPLIT, nativeSplit, maybeCallNative) { + var internalSplit; + if ( + 'abbc'.split(/(b)*/)[1] == 'c' || + // eslint-disable-next-line regexp/no-empty-group -- required for testing + 'test'.split(/(?:)/, -1).length != 4 || + 'ab'.split(/(?:ab)*/).length != 2 || + '.'.split(/(.?)(.?)/).length != 4 || + // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing + '.'.split(/()()/).length > 1 || + ''.split(/.?/).length + ) { + // based on es5-shim implementation, need to rework it + internalSplit = function (separator, limit) { + var string = String(requireObjectCoercible(this)); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (separator === undefined) return [string]; + // If `separator` is not a regex, use native split + if (!isRegexp(separator)) { + return nativeSplit.call(string, separator, lim); + } + var output = []; + var flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.unicode ? 'u' : '') + + (separator.sticky ? 'y' : ''); + var lastLastIndex = 0; + // Make `global` and avoid `lastIndex` issues by working with a copy + var separatorCopy = new RegExp(separator.source, flags + 'g'); + var match, lastIndex, lastLength; + while (match = regexpExec.call(separatorCopy, string)) { + lastIndex = separatorCopy.lastIndex; + if (lastIndex > lastLastIndex) { + output.push(string.slice(lastLastIndex, match.index)); + if (match.length > 1 && match.index < string.length) arrayPush.apply(output, match.slice(1)); + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= lim) break; + } + if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop + } + if (lastLastIndex === string.length) { + if (lastLength || !separatorCopy.test('')) output.push(''); + } else output.push(string.slice(lastLastIndex)); + return output.length > lim ? output.slice(0, lim) : output; + }; + // Chakra, V8 + } else if ('0'.split(undefined, 0).length) { + internalSplit = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : nativeSplit.call(this, separator, limit); + }; + } else internalSplit = nativeSplit; + + return [ + // `String.prototype.split` method + // https://tc39.es/ecma262/#sec-string.prototype.split + function split(separator, limit) { + var O = requireObjectCoercible(this); + var splitter = separator == undefined ? undefined : separator[SPLIT]; + return splitter !== undefined + ? splitter.call(separator, O, limit) + : internalSplit.call(String(O), separator, limit); + }, + // `RegExp.prototype[@@split]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@split + // + // NOTE: This cannot be properly polyfilled in engines that don't support + // the 'y' flag. + function (regexp, limit) { + var res = maybeCallNative(internalSplit, regexp, this, limit, internalSplit !== nativeSplit); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + var C = speciesConstructor(rx, RegExp); + + var unicodeMatching = rx.unicode; + var flags = (rx.ignoreCase ? 'i' : '') + + (rx.multiline ? 'm' : '') + + (rx.unicode ? 'u' : '') + + (SUPPORTS_Y ? 'y' : 'g'); + + // ^(? + rx + ) is needed, in combination with some S slicing, to + // simulate the 'y' flag. + var splitter = new C(SUPPORTS_Y ? rx : '^(?:' + rx.source + ')', flags); + var lim = limit === undefined ? MAX_UINT32 : limit >>> 0; + if (lim === 0) return []; + if (S.length === 0) return regexpExecAbstract(splitter, S) === null ? [S] : []; + var p = 0; + var q = 0; + var A = []; + while (q < S.length) { + splitter.lastIndex = SUPPORTS_Y ? q : 0; + var z = regexpExecAbstract(splitter, SUPPORTS_Y ? S : S.slice(q)); + var e; + if ( + z === null || + (e = min$4(toLength(splitter.lastIndex + (SUPPORTS_Y ? 0 : q)), S.length)) === p + ) { + q = advanceStringIndex(S, q, unicodeMatching); + } else { + A.push(S.slice(p, q)); + if (A.length === lim) return A; + for (var i = 1; i <= z.length - 1; i++) { + A.push(z[i]); + if (A.length === lim) return A; + } + q = p = e; + } + } + A.push(S.slice(p)); + return A; + } + ]; + }, !SUPPORTS_Y); + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + var objectKeys = Object.keys || function keys(O) { + return objectKeysInternal(O, enumBugKeys); + }; + + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = objectKeys(Properties); + var length = keys.length; + var index = 0; + var key; + while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]); + return O; + }; + + var html = getBuiltIn('document', 'documentElement'); + + var GT = '>'; + var LT = '<'; + var PROTOTYPE = 'prototype'; + var SCRIPT = 'script'; + var IE_PROTO$1 = sharedKey('IE_PROTO'); + + var EmptyConstructor = function () { /* empty */ }; + + var scriptTag = function (content) { + return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT; + }; + + // Create object with fake `null` prototype: use ActiveX Object with cleared prototype + var NullProtoObjectViaActiveX = function (activeXDocument) { + activeXDocument.write(scriptTag('')); + activeXDocument.close(); + var temp = activeXDocument.parentWindow.Object; + activeXDocument = null; // avoid memory leak + return temp; + }; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var NullProtoObjectViaIFrame = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = documentCreateElement('iframe'); + var JS = 'java' + SCRIPT + ':'; + var iframeDocument; + iframe.style.display = 'none'; + html.appendChild(iframe); + // https://github.com/zloirock/core-js/issues/475 + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag('document.F=Object')); + iframeDocument.close(); + return iframeDocument.F; + }; + + // Check for document.domain and active x support + // No need to use active x approach when document.domain is not set + // see https://github.com/es-shims/es5-shim/issues/150 + // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 + // avoid IE GC bug + var activeXDocument; + var NullProtoObject = function () { + try { + /* global ActiveXObject -- old IE */ + activeXDocument = document.domain && new ActiveXObject('htmlfile'); + } catch (error) { /* ignore */ } + NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame(); + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]]; + return NullProtoObject(); + }; + + hiddenKeys$1[IE_PROTO$1] = true; + + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + var objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + EmptyConstructor[PROTOTYPE] = anObject(O); + result = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO$1] = O; + } else result = NullProtoObject(); + return Properties === undefined ? result : objectDefineProperties(result, Properties); + }; + + var UNSCOPABLES = wellKnownSymbol('unscopables'); + var ArrayPrototype = Array.prototype; + + // Array.prototype[@@unscopables] + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + if (ArrayPrototype[UNSCOPABLES] == undefined) { + objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, { + configurable: true, + value: objectCreate(null) + }); + } + + // add a key to Array.prototype[@@unscopables] + var addToUnscopables = function (key) { + ArrayPrototype[UNSCOPABLES][key] = true; + }; + + var $includes = arrayIncludes.includes; + + + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + _export({ target: 'Array', proto: true }, { + includes: function includes(el /* , fromIndex = 0 */) { + return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables('includes'); + + // `IsArray` abstract operation + // https://tc39.es/ecma262/#sec-isarray + var isArray = Array.isArray || function isArray(arg) { + return classofRaw(arg) == 'Array'; + }; + + // `ToObject` abstract operation + // https://tc39.es/ecma262/#sec-toobject + var toObject = function (argument) { + return Object(requireObjectCoercible(argument)); + }; + + var createProperty = function (object, key, value) { + var propertyKey = toPrimitive(key); + if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value)); + else object[propertyKey] = value; + }; + + var SPECIES$3 = wellKnownSymbol('species'); + + // `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesCreate = function (originalArray, length) { + var C; + if (isArray(originalArray)) { + C = originalArray.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; + else if (isObject(C)) { + C = C[SPECIES$3]; + if (C === null) C = undefined; + } + } return new (C === undefined ? Array : C)(length === 0 ? 0 : length); + }; + + var SPECIES$2 = wellKnownSymbol('species'); + + var arrayMethodHasSpeciesSupport = function (METHOD_NAME) { + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/677 + return engineV8Version >= 51 || !fails(function () { + var array = []; + var constructor = array.constructor = {}; + constructor[SPECIES$2] = function () { + return { foo: 1 }; + }; + return array[METHOD_NAME](Boolean).foo !== 1; + }); + }; + + var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable'); + var MAX_SAFE_INTEGER$1 = 0x1FFFFFFFFFFFFF; + var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded'; + + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/679 + var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () { + var array = []; + array[IS_CONCAT_SPREADABLE] = false; + return array.concat()[0] !== array; + }); + + var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat'); + + var isConcatSpreadable = function (O) { + if (!isObject(O)) return false; + var spreadable = O[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray(O); + }; + + var FORCED$4 = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT; + + // `Array.prototype.concat` method + // https://tc39.es/ecma262/#sec-array.prototype.concat + // with adding support of @@isConcatSpreadable and @@species + _export({ target: 'Array', proto: true, forced: FORCED$4 }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + concat: function concat(arg) { + var O = toObject(this); + var A = arraySpeciesCreate(O, 0); + var n = 0; + var i, k, length, len, E; + for (i = -1, length = arguments.length; i < length; i++) { + E = i === -1 ? O : arguments[i]; + if (isConcatSpreadable(E)) { + len = toLength(E.length); + if (n + len > MAX_SAFE_INTEGER$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]); + } else { + if (n >= MAX_SAFE_INTEGER$1) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + createProperty(A, n++, E); + } + } + A.length = n; + return A; + } + }); + + // optional / simple context binding + var functionBindContext = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 0: return function () { + return fn.call(that); + }; + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; + }; + + var push = [].push; + + // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation + var createMethod$1 = function (TYPE) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var IS_FILTER_OUT = TYPE == 7; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + return function ($this, callbackfn, that, specificCreate) { + var O = toObject($this); + var self = indexedObject(O); + var boundFunction = functionBindContext(callbackfn, that, 3); + var length = toLength(self.length); + var index = 0; + var create = specificCreate || arraySpeciesCreate; + var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_OUT ? create($this, 0) : undefined; + var value, result; + for (;length > index; index++) if (NO_HOLES || index in self) { + value = self[index]; + result = boundFunction(value, index, O); + if (TYPE) { + if (IS_MAP) target[index] = result; // map + else if (result) switch (TYPE) { + case 3: return true; // some + case 5: return value; // find + case 6: return index; // findIndex + case 2: push.call(target, value); // filter + } else switch (TYPE) { + case 4: return false; // every + case 7: push.call(target, value); // filterOut + } + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target; + }; + }; + + var arrayIteration = { + // `Array.prototype.forEach` method + // https://tc39.es/ecma262/#sec-array.prototype.foreach + forEach: createMethod$1(0), + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + map: createMethod$1(1), + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + filter: createMethod$1(2), + // `Array.prototype.some` method + // https://tc39.es/ecma262/#sec-array.prototype.some + some: createMethod$1(3), + // `Array.prototype.every` method + // https://tc39.es/ecma262/#sec-array.prototype.every + every: createMethod$1(4), + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + find: createMethod$1(5), + // `Array.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-array.prototype.findIndex + findIndex: createMethod$1(6), + // `Array.prototype.filterOut` method + // https://github.com/tc39/proposal-array-filtering + filterOut: createMethod$1(7) + }; + + var $find = arrayIteration.find; + + + var FIND = 'find'; + var SKIPS_HOLES$1 = true; + + // Shouldn't skip holes + if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES$1 = false; }); + + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + _export({ target: 'Array', proto: true, forced: SKIPS_HOLES$1 }, { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables(FIND); + + var notARegexp = function (it) { + if (isRegexp(it)) { + throw TypeError("The method doesn't accept regular expressions"); + } return it; + }; + + var MATCH$1 = wellKnownSymbol('match'); + + var correctIsRegexpLogic = function (METHOD_NAME) { + var regexp = /./; + try { + '/./'[METHOD_NAME](regexp); + } catch (error1) { + try { + regexp[MATCH$1] = false; + return '/./'[METHOD_NAME](regexp); + } catch (error2) { /* empty */ } + } return false; + }; + + // `String.prototype.includes` method + // https://tc39.es/ecma262/#sec-string.prototype.includes + _export({ target: 'String', proto: true, forced: !correctIsRegexpLogic('includes') }, { + includes: function includes(searchString /* , position = 0 */) { + return !!~String(requireObjectCoercible(this)) + .indexOf(notARegexp(searchString), arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // iterable DOM collections + // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods + var domIterables = { + CSSRuleList: 0, + CSSStyleDeclaration: 0, + CSSValueList: 0, + ClientRectList: 0, + DOMRectList: 0, + DOMStringList: 0, + DOMTokenList: 1, + DataTransferItemList: 0, + FileList: 0, + HTMLAllCollection: 0, + HTMLCollection: 0, + HTMLFormElement: 0, + HTMLSelectElement: 0, + MediaList: 0, + MimeTypeArray: 0, + NamedNodeMap: 0, + NodeList: 1, + PaintRequestList: 0, + Plugin: 0, + PluginArray: 0, + SVGLengthList: 0, + SVGNumberList: 0, + SVGPathSegList: 0, + SVGPointList: 0, + SVGStringList: 0, + SVGTransformList: 0, + SourceBufferList: 0, + StyleSheetList: 0, + TextTrackCueList: 0, + TextTrackList: 0, + TouchList: 0 + }; + + var $forEach = arrayIteration.forEach; + + + var STRICT_METHOD$2 = arrayMethodIsStrict('forEach'); + + // `Array.prototype.forEach` method implementation + // https://tc39.es/ecma262/#sec-array.prototype.foreach + var arrayForEach = !STRICT_METHOD$2 ? function forEach(callbackfn /* , thisArg */) { + return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } : [].forEach; + + for (var COLLECTION_NAME$1 in domIterables) { + var Collection$1 = global_1[COLLECTION_NAME$1]; + var CollectionPrototype$1 = Collection$1 && Collection$1.prototype; + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype$1 && CollectionPrototype$1.forEach !== arrayForEach) try { + createNonEnumerableProperty(CollectionPrototype$1, 'forEach', arrayForEach); + } catch (error) { + CollectionPrototype$1.forEach = arrayForEach; + } + } + + var trim$2 = stringTrim.trim; + + + var $parseFloat = global_1.parseFloat; + var FORCED$3 = 1 / $parseFloat(whitespaces + '-0') !== -Infinity; + + // `parseFloat` method + // https://tc39.es/ecma262/#sec-parsefloat-string + var numberParseFloat = FORCED$3 ? function parseFloat(string) { + var trimmedString = trim$2(String(string)); + var result = $parseFloat(trimmedString); + return result === 0 && trimmedString.charAt(0) == '-' ? -0 : result; + } : $parseFloat; + + // `parseFloat` method + // https://tc39.es/ecma262/#sec-parsefloat-string + _export({ global: true, forced: parseFloat != numberParseFloat }, { + parseFloat: numberParseFloat + }); + + var propertyIsEnumerable = objectPropertyIsEnumerable.f; + + // `Object.{ entries, values }` methods implementation + var createMethod = function (TO_ENTRIES) { + return function (it) { + var O = toIndexedObject(it); + var keys = objectKeys(O); + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) { + key = keys[i++]; + if (!descriptors || propertyIsEnumerable.call(O, key)) { + result.push(TO_ENTRIES ? [key, O[key]] : O[key]); + } + } + return result; + }; + }; + + var objectToArray = { + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + entries: createMethod(true), + // `Object.values` method + // https://tc39.es/ecma262/#sec-object.values + values: createMethod(false) + }; + + var $entries = objectToArray.entries; + + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + _export({ target: 'Object', stat: true }, { + entries: function entries(O) { + return $entries(O); + } + }); + + var $indexOf = arrayIncludes.indexOf; + + + var nativeIndexOf = [].indexOf; + + var NEGATIVE_ZERO = !!nativeIndexOf && 1 / [1].indexOf(1, -0) < 0; + var STRICT_METHOD$1 = arrayMethodIsStrict('indexOf'); + + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + _export({ target: 'Array', proto: true, forced: NEGATIVE_ZERO || !STRICT_METHOD$1 }, { + indexOf: function indexOf(searchElement /* , fromIndex = 0 */) { + return NEGATIVE_ZERO + // convert -0 to +0 + ? nativeIndexOf.apply(this, arguments) || 0 + : $indexOf(this, searchElement, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var test$2 = []; + var nativeSort = test$2.sort; + + // IE8- + var FAILS_ON_UNDEFINED = fails(function () { + test$2.sort(undefined); + }); + // V8 bug + var FAILS_ON_NULL = fails(function () { + test$2.sort(null); + }); + // Old WebKit + var STRICT_METHOD = arrayMethodIsStrict('sort'); + + var FORCED$2 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD; + + // `Array.prototype.sort` method + // https://tc39.es/ecma262/#sec-array.prototype.sort + _export({ target: 'Array', proto: true, forced: FORCED$2 }, { + sort: function sort(comparefn) { + return comparefn === undefined + ? nativeSort.call(toObject(this)) + : nativeSort.call(toObject(this), aFunction(comparefn)); + } + }); + + var floor = Math.floor; + var replace = ''.replace; + var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g; + var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g; + + // https://tc39.es/ecma262/#sec-getsubstitution + var getSubstitution = function (matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = toObject(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return replace.call(replacement, symbols, function (match, ch) { + var capture; + switch (ch.charAt(0)) { + case '$': return '$'; + case '&': return matched; + case '`': return str.slice(0, position); + case "'": return str.slice(tailPos); + case '<': + capture = namedCaptures[ch.slice(1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return match; + if (n > m) { + var f = floor(n / 10); + if (f === 0) return match; + if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); + return match; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + }; + + var max$2 = Math.max; + var min$3 = Math.min; + + var maybeToString = function (it) { + return it === undefined ? it : String(it); + }; + + // @@replace logic + fixRegexpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative, reason) { + var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = reason.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE; + var REPLACE_KEEPS_$0 = reason.REPLACE_KEEPS_$0; + var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0'; + + return [ + // `String.prototype.replace` method + // https://tc39.es/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = requireObjectCoercible(this); + var replacer = searchValue == undefined ? undefined : searchValue[REPLACE]; + return replacer !== undefined + ? replacer.call(searchValue, O, replaceValue) + : nativeReplace.call(String(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace + function (regexp, replaceValue) { + if ( + (!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_$0) || + (typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1) + ) { + var res = maybeCallNative(nativeReplace, regexp, this, replaceValue); + if (res.done) return res.value; + } + + var rx = anObject(regexp); + var S = String(this); + + var functionalReplace = typeof replaceValue === 'function'; + if (!functionalReplace) replaceValue = String(replaceValue); + + var global = rx.global; + if (global) { + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + var results = []; + while (true) { + var result = regexpExecAbstract(rx, S); + if (result === null) break; + + results.push(result); + if (!global) break; + + var matchStr = String(result[0]); + if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); + } + + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + + var matched = String(result[0]); + var position = max$2(min$3(toInteger(result.index), S.length), 0); + var captures = []; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = [matched].concat(captures, position, S); + if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); + var replacement = String(replaceValue.apply(undefined, replacerArgs)); + } else { + replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += S.slice(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + return accumulatedResult + S.slice(nextSourcePosition); + } + ]; + }); + + var nativeAssign = Object.assign; + var defineProperty$3 = Object.defineProperty; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + var objectAssign = !nativeAssign || fails(function () { + // should have correct order of operations (Edge bug) + if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty$3({}, 'a', { + enumerable: true, + get: function () { + defineProperty$3(this, 'b', { + value: 3, + enumerable: false + }); + } + }), { b: 2 })).b !== 1) return true; + // should work with symbols and should have deterministic property order (V8 bug) + var A = {}; + var B = {}; + /* global Symbol -- required for testing */ + var symbol = Symbol(); + var alphabet = 'abcdefghijklmnopqrst'; + A[symbol] = 7; + alphabet.split('').forEach(function (chr) { B[chr] = chr; }); + return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet; + }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length` + var T = toObject(target); + var argumentsLength = arguments.length; + var index = 1; + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + var propertyIsEnumerable = objectPropertyIsEnumerable.f; + while (argumentsLength > index) { + var S = indexedObject(arguments[index++]); + var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) { + key = keys[j++]; + if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key]; + } + } return T; + } : nativeAssign; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + _export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, { + assign: objectAssign + }); + + var $filter = arrayIteration.filter; + + + var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport('filter'); + + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + // with adding support of @@species + _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, { + filter: function filter(callbackfn /* , thisArg */) { + return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // `SameValue` abstract operation + // https://tc39.es/ecma262/#sec-samevalue + var sameValue = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare -- NaN check + return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; + }; + + // @@search logic + fixRegexpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.es/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = requireObjectCoercible(this); + var searcher = regexp == undefined ? undefined : regexp[SEARCH]; + return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@search + function (regexp) { + var res = maybeCallNative(nativeSearch, regexp, this); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + + var previousLastIndex = rx.lastIndex; + if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = regexpExecAbstract(rx, S); + if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; + }); + + var trim$1 = stringTrim.trim; + + + var $parseInt = global_1.parseInt; + var hex = /^[+-]?0[Xx]/; + var FORCED$1 = $parseInt(whitespaces + '08') !== 8 || $parseInt(whitespaces + '0x16') !== 22; + + // `parseInt` method + // https://tc39.es/ecma262/#sec-parseint-string-radix + var numberParseInt = FORCED$1 ? function parseInt(string, radix) { + var S = trim$1(String(string)); + return $parseInt(S, (radix >>> 0) || (hex.test(S) ? 16 : 10)); + } : $parseInt; + + // `parseInt` method + // https://tc39.es/ecma262/#sec-parseint-string-radix + _export({ global: true, forced: parseInt != numberParseInt }, { + parseInt: numberParseInt + }); + + var $map = arrayIteration.map; + + + var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport('map'); + + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + // with adding support of @@species + _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, { + map: function map(callbackfn /* , thisArg */) { + return $map(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + var $findIndex = arrayIteration.findIndex; + + + var FIND_INDEX = 'findIndex'; + var SKIPS_HOLES = true; + + // Shouldn't skip holes + if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; }); + + // `Array.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-array.prototype.findindex + _export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, { + findIndex: function findIndex(callbackfn /* , that = undefined */) { + return $findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables(FIND_INDEX); + + var aPossiblePrototype = function (it) { + if (!isObject(it) && it !== null) { + throw TypeError("Can't set " + String(it) + ' as a prototype'); + } return it; + }; + + /* eslint-disable no-proto -- safe */ + + + + // `Object.setPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.setprototypeof + // Works with __proto__ only. Old v8 can't work with null proto objects. + var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () { + var CORRECT_SETTER = false; + var test = {}; + var setter; + try { + setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set; + setter.call(test, []); + CORRECT_SETTER = test instanceof Array; + } catch (error) { /* empty */ } + return function setPrototypeOf(O, proto) { + anObject(O); + aPossiblePrototype(proto); + if (CORRECT_SETTER) setter.call(O, proto); + else O.__proto__ = proto; + return O; + }; + }() : undefined); + + // makes subclassing work correct for wrapped built-ins + var inheritIfRequired = function ($this, dummy, Wrapper) { + var NewTarget, NewTargetPrototype; + if ( + // it can work only with native `setPrototypeOf` + objectSetPrototypeOf && + // we haven't completely correct pre-ES6 way for getting `new.target`, so use this + typeof (NewTarget = dummy.constructor) == 'function' && + NewTarget !== Wrapper && + isObject(NewTargetPrototype = NewTarget.prototype) && + NewTargetPrototype !== Wrapper.prototype + ) objectSetPrototypeOf($this, NewTargetPrototype); + return $this; + }; + + var SPECIES$1 = wellKnownSymbol('species'); + + var setSpecies = function (CONSTRUCTOR_NAME) { + var Constructor = getBuiltIn(CONSTRUCTOR_NAME); + var defineProperty = objectDefineProperty.f; + + if (descriptors && Constructor && !Constructor[SPECIES$1]) { + defineProperty(Constructor, SPECIES$1, { + configurable: true, + get: function () { return this; } + }); + } + }; + + var defineProperty$2 = objectDefineProperty.f; + var getOwnPropertyNames$1 = objectGetOwnPropertyNames.f; + + + + + + var setInternalState$1 = internalState.set; + + + + var MATCH = wellKnownSymbol('match'); + var NativeRegExp = global_1.RegExp; + var RegExpPrototype$1 = NativeRegExp.prototype; + var re1 = /a/g; + var re2 = /a/g; + + // "new" should create a new object, old webkit bug + var CORRECT_NEW = new NativeRegExp(re1) !== re1; + + var UNSUPPORTED_Y = regexpStickyHelpers.UNSUPPORTED_Y; + + var FORCED = descriptors && isForced_1('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () { + re2[MATCH] = false; + // RegExp constructor can alter flags and IsRegExp works correct with @@match + return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i'; + }))); + + // `RegExp` constructor + // https://tc39.es/ecma262/#sec-regexp-constructor + if (FORCED) { + var RegExpWrapper = function RegExp(pattern, flags) { + var thisIsRegExp = this instanceof RegExpWrapper; + var patternIsRegExp = isRegexp(pattern); + var flagsAreUndefined = flags === undefined; + var sticky; + + if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) { + return pattern; + } + + if (CORRECT_NEW) { + if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source; + } else if (pattern instanceof RegExpWrapper) { + if (flagsAreUndefined) flags = regexpFlags.call(pattern); + pattern = pattern.source; + } + + if (UNSUPPORTED_Y) { + sticky = !!flags && flags.indexOf('y') > -1; + if (sticky) flags = flags.replace(/y/g, ''); + } + + var result = inheritIfRequired( + CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags), + thisIsRegExp ? this : RegExpPrototype$1, + RegExpWrapper + ); + + if (UNSUPPORTED_Y && sticky) setInternalState$1(result, { sticky: sticky }); + + return result; + }; + var proxy = function (key) { + key in RegExpWrapper || defineProperty$2(RegExpWrapper, key, { + configurable: true, + get: function () { return NativeRegExp[key]; }, + set: function (it) { NativeRegExp[key] = it; } + }); + }; + var keys$1 = getOwnPropertyNames$1(NativeRegExp); + var index = 0; + while (keys$1.length > index) proxy(keys$1[index++]); + RegExpPrototype$1.constructor = RegExpWrapper; + RegExpWrapper.prototype = RegExpPrototype$1; + redefine(global_1, 'RegExp', RegExpWrapper); + } + + // https://tc39.es/ecma262/#sec-get-regexp-@@species + setSpecies('RegExp'); + + var TO_STRING = 'toString'; + var RegExpPrototype = RegExp.prototype; + var nativeToString = RegExpPrototype[TO_STRING]; + + var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; }); + // FF44- RegExp#toString has a wrong name + var INCORRECT_NAME = nativeToString.name != TO_STRING; + + // `RegExp.prototype.toString` method + // https://tc39.es/ecma262/#sec-regexp.prototype.tostring + if (NOT_GENERIC || INCORRECT_NAME) { + redefine(RegExp.prototype, TO_STRING, function toString() { + var R = anObject(this); + var p = String(R.source); + var rf = R.flags; + var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? regexpFlags.call(R) : rf); + return '/' + p + '/' + f; + }, { unsafe: true }); + } + + var TO_STRING_TAG$3 = wellKnownSymbol('toStringTag'); + var test$1 = {}; + + test$1[TO_STRING_TAG$3] = 'z'; + + var toStringTagSupport = String(test$1) === '[object z]'; + + var TO_STRING_TAG$2 = wellKnownSymbol('toStringTag'); + // ES3 wrong here + var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments'; + + // fallback for IE11 Script Access Denied error + var tryGet = function (it, key) { + try { + return it[key]; + } catch (error) { /* empty */ } + }; + + // getting tag from ES6+ `Object.prototype.toString` + var classof = toStringTagSupport ? classofRaw : function (it) { + var O, tag, result; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (tag = tryGet(O = Object(it), TO_STRING_TAG$2)) == 'string' ? tag + // builtinTag case + : CORRECT_ARGUMENTS ? classofRaw(O) + // ES3 arguments fallback + : (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : result; + }; + + // `Object.prototype.toString` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.tostring + var objectToString = toStringTagSupport ? {}.toString : function toString() { + return '[object ' + classof(this) + ']'; + }; + + // `Object.prototype.toString` method + // https://tc39.es/ecma262/#sec-object.prototype.tostring + if (!toStringTagSupport) { + redefine(Object.prototype, 'toString', objectToString, { unsafe: true }); + } + + var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport('slice'); + + var SPECIES = wellKnownSymbol('species'); + var nativeSlice = [].slice; + var max$1 = Math.max; + + // `Array.prototype.slice` method + // https://tc39.es/ecma262/#sec-array.prototype.slice + // fallback for not array-like ES3 strings and DOM objects + _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, { + slice: function slice(start, end) { + var O = toIndexedObject(this); + var length = toLength(O.length); + var k = toAbsoluteIndex(start, length); + var fin = toAbsoluteIndex(end === undefined ? length : end, length); + // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible + var Constructor, result, n; + if (isArray(O)) { + Constructor = O.constructor; + // cross-realm fallback + if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) { + Constructor = undefined; + } else if (isObject(Constructor)) { + Constructor = Constructor[SPECIES]; + if (Constructor === null) Constructor = undefined; + } + if (Constructor === Array || Constructor === undefined) { + return nativeSlice.call(O, k, fin); + } + } + result = new (Constructor === undefined ? Array : Constructor)(max$1(fin - k, 0)); + for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]); + result.length = n; + return result; + } + }); + + var correctPrototypeGetter = !fails(function () { + function F() { /* empty */ } + F.prototype.constructor = null; + return Object.getPrototypeOf(new F()) !== F.prototype; + }); + + var IE_PROTO = sharedKey('IE_PROTO'); + var ObjectPrototype = Object.prototype; + + // `Object.getPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.getprototypeof + var objectGetPrototypeOf = correctPrototypeGetter ? Object.getPrototypeOf : function (O) { + O = toObject(O); + if (has$1(O, IE_PROTO)) return O[IE_PROTO]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectPrototype : null; + }; + + var ITERATOR$2 = wellKnownSymbol('iterator'); + var BUGGY_SAFARI_ITERATORS$1 = false; + + var returnThis$1 = function () { return this; }; + + // `%IteratorPrototype%` object + // https://tc39.es/ecma262/#sec-%iteratorprototype%-object + var IteratorPrototype$2, PrototypeOfArrayIteratorPrototype, arrayIterator; + + if ([].keys) { + arrayIterator = [].keys(); + // Safari 8 has buggy iterators w/o `next` + if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true; + else { + PrototypeOfArrayIteratorPrototype = objectGetPrototypeOf(objectGetPrototypeOf(arrayIterator)); + if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$2 = PrototypeOfArrayIteratorPrototype; + } + } + + var NEW_ITERATOR_PROTOTYPE = IteratorPrototype$2 == undefined || fails(function () { + var test = {}; + // FF44- legacy iterators case + return IteratorPrototype$2[ITERATOR$2].call(test) !== test; + }); + + if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$2 = {}; + + // 25.1.2.1.1 %IteratorPrototype%[@@iterator]() + if (!has$1(IteratorPrototype$2, ITERATOR$2)) { + createNonEnumerableProperty(IteratorPrototype$2, ITERATOR$2, returnThis$1); + } + + var iteratorsCore = { + IteratorPrototype: IteratorPrototype$2, + BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1 + }; + + var defineProperty$1 = objectDefineProperty.f; + + + + var TO_STRING_TAG$1 = wellKnownSymbol('toStringTag'); + + var setToStringTag = function (it, TAG, STATIC) { + if (it && !has$1(it = STATIC ? it : it.prototype, TO_STRING_TAG$1)) { + defineProperty$1(it, TO_STRING_TAG$1, { configurable: true, value: TAG }); + } + }; + + var IteratorPrototype$1 = iteratorsCore.IteratorPrototype; + + var createIteratorConstructor = function (IteratorConstructor, NAME, next) { + var TO_STRING_TAG = NAME + ' Iterator'; + IteratorConstructor.prototype = objectCreate(IteratorPrototype$1, { next: createPropertyDescriptor(1, next) }); + setToStringTag(IteratorConstructor, TO_STRING_TAG, false); + return IteratorConstructor; + }; + + var IteratorPrototype = iteratorsCore.IteratorPrototype; + var BUGGY_SAFARI_ITERATORS = iteratorsCore.BUGGY_SAFARI_ITERATORS; + var ITERATOR$1 = wellKnownSymbol('iterator'); + var KEYS = 'keys'; + var VALUES = 'values'; + var ENTRIES = 'entries'; + + var returnThis = function () { return this; }; + + var defineIterator = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) { + createIteratorConstructor(IteratorConstructor, NAME, next); + + var getIterationMethod = function (KIND) { + if (KIND === DEFAULT && defaultIterator) return defaultIterator; + if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND]; + switch (KIND) { + case KEYS: return function keys() { return new IteratorConstructor(this, KIND); }; + case VALUES: return function values() { return new IteratorConstructor(this, KIND); }; + case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); }; + } return function () { return new IteratorConstructor(this); }; + }; + + var TO_STRING_TAG = NAME + ' Iterator'; + var INCORRECT_VALUES_NAME = false; + var IterablePrototype = Iterable.prototype; + var nativeIterator = IterablePrototype[ITERATOR$1] + || IterablePrototype['@@iterator'] + || DEFAULT && IterablePrototype[DEFAULT]; + var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT); + var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator; + var CurrentIteratorPrototype, methods, KEY; + + // fix native + if (anyNativeIterator) { + CurrentIteratorPrototype = objectGetPrototypeOf(anyNativeIterator.call(new Iterable())); + if (IteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) { + if (objectGetPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) { + if (objectSetPrototypeOf) { + objectSetPrototypeOf(CurrentIteratorPrototype, IteratorPrototype); + } else if (typeof CurrentIteratorPrototype[ITERATOR$1] != 'function') { + createNonEnumerableProperty(CurrentIteratorPrototype, ITERATOR$1, returnThis); + } + } + // Set @@toStringTag to native iterators + setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true); + } + } + + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) { + INCORRECT_VALUES_NAME = true; + defaultIterator = function values() { return nativeIterator.call(this); }; + } + + // define iterator + if (IterablePrototype[ITERATOR$1] !== defaultIterator) { + createNonEnumerableProperty(IterablePrototype, ITERATOR$1, defaultIterator); + } + + // export additional methods + if (DEFAULT) { + methods = { + values: getIterationMethod(VALUES), + keys: IS_SET ? defaultIterator : getIterationMethod(KEYS), + entries: getIterationMethod(ENTRIES) + }; + if (FORCED) for (KEY in methods) { + if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) { + redefine(IterablePrototype, KEY, methods[KEY]); + } + } else _export({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods); + } + + return methods; + }; + + var ARRAY_ITERATOR = 'Array Iterator'; + var setInternalState = internalState.set; + var getInternalState = internalState.getterFor(ARRAY_ITERATOR); + + // `Array.prototype.entries` method + // https://tc39.es/ecma262/#sec-array.prototype.entries + // `Array.prototype.keys` method + // https://tc39.es/ecma262/#sec-array.prototype.keys + // `Array.prototype.values` method + // https://tc39.es/ecma262/#sec-array.prototype.values + // `Array.prototype[@@iterator]` method + // https://tc39.es/ecma262/#sec-array.prototype-@@iterator + // `CreateArrayIterator` internal method + // https://tc39.es/ecma262/#sec-createarrayiterator + var es_array_iterator = defineIterator(Array, 'Array', function (iterated, kind) { + setInternalState(this, { + type: ARRAY_ITERATOR, + target: toIndexedObject(iterated), // target + index: 0, // next index + kind: kind // kind + }); + // `%ArrayIteratorPrototype%.next` method + // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next + }, function () { + var state = getInternalState(this); + var target = state.target; + var kind = state.kind; + var index = state.index++; + if (!target || index >= target.length) { + state.target = undefined; + return { value: undefined, done: true }; + } + if (kind == 'keys') return { value: index, done: false }; + if (kind == 'values') return { value: target[index], done: false }; + return { value: [index, target[index]], done: false }; + }, 'values'); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables('keys'); + addToUnscopables('values'); + addToUnscopables('entries'); + + var ITERATOR = wellKnownSymbol('iterator'); + var TO_STRING_TAG = wellKnownSymbol('toStringTag'); + var ArrayValues = es_array_iterator.values; + + for (var COLLECTION_NAME in domIterables) { + var Collection = global_1[COLLECTION_NAME]; + var CollectionPrototype = Collection && Collection.prototype; + if (CollectionPrototype) { + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype[ITERATOR] !== ArrayValues) try { + createNonEnumerableProperty(CollectionPrototype, ITERATOR, ArrayValues); + } catch (error) { + CollectionPrototype[ITERATOR] = ArrayValues; + } + if (!CollectionPrototype[TO_STRING_TAG]) { + createNonEnumerableProperty(CollectionPrototype, TO_STRING_TAG, COLLECTION_NAME); + } + if (domIterables[COLLECTION_NAME]) for (var METHOD_NAME in es_array_iterator) { + // some Chrome versions have non-configurable methods on DOMTokenList + if (CollectionPrototype[METHOD_NAME] !== es_array_iterator[METHOD_NAME]) try { + createNonEnumerableProperty(CollectionPrototype, METHOD_NAME, es_array_iterator[METHOD_NAME]); + } catch (error) { + CollectionPrototype[METHOD_NAME] = es_array_iterator[METHOD_NAME]; + } + } + } + } + + var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('splice'); + + var max = Math.max; + var min$2 = Math.min; + var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; + var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded'; + + // `Array.prototype.splice` method + // https://tc39.es/ecma262/#sec-array.prototype.splice + // with adding support of @@species + _export({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, { + splice: function splice(start, deleteCount /* , ...items */) { + var O = toObject(this); + var len = toLength(O.length); + var actualStart = toAbsoluteIndex(start, len); + var argumentsLength = arguments.length; + var insertCount, actualDeleteCount, A, k, from, to; + if (argumentsLength === 0) { + insertCount = actualDeleteCount = 0; + } else if (argumentsLength === 1) { + insertCount = 0; + actualDeleteCount = len - actualStart; + } else { + insertCount = argumentsLength - 2; + actualDeleteCount = min$2(max(toInteger(deleteCount), 0), len - actualStart); + } + if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER) { + throw TypeError(MAXIMUM_ALLOWED_LENGTH_EXCEEDED); + } + A = arraySpeciesCreate(O, actualDeleteCount); + for (k = 0; k < actualDeleteCount; k++) { + from = actualStart + k; + if (from in O) createProperty(A, k, O[from]); + } + A.length = actualDeleteCount; + if (insertCount < actualDeleteCount) { + for (k = actualStart; k < len - actualDeleteCount; k++) { + from = k + actualDeleteCount; + to = k + insertCount; + if (from in O) O[to] = O[from]; + else delete O[to]; + } + for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1]; + } else if (insertCount > actualDeleteCount) { + for (k = len - actualDeleteCount; k > actualStart; k--) { + from = k + actualDeleteCount - 1; + to = k + insertCount - 1; + if (from in O) O[to] = O[from]; + else delete O[to]; + } + } + for (k = 0; k < insertCount; k++) { + O[k + actualStart] = arguments[k + 2]; + } + O.length = len - actualDeleteCount + insertCount; + return A; + } + }); + + var getOwnPropertyNames = objectGetOwnPropertyNames.f; + var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f; + var defineProperty = objectDefineProperty.f; + var trim = stringTrim.trim; + + var NUMBER = 'Number'; + var NativeNumber = global_1[NUMBER]; + var NumberPrototype = NativeNumber.prototype; + + // Opera ~12 has broken Object#toString + var BROKEN_CLASSOF = classofRaw(objectCreate(NumberPrototype)) == NUMBER; + + // `ToNumber` abstract operation + // https://tc39.es/ecma262/#sec-tonumber + var toNumber = function (argument) { + var it = toPrimitive(argument, false); + var first, third, radix, maxCode, digits, length, index, code; + if (typeof it == 'string' && it.length > 2) { + it = trim(it); + first = it.charCodeAt(0); + if (first === 43 || first === 45) { + third = it.charCodeAt(2); + if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix + } else if (first === 48) { + switch (it.charCodeAt(1)) { + case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+$/i + case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+$/i + default: return +it; + } + digits = it.slice(2); + length = digits.length; + for (index = 0; index < length; index++) { + code = digits.charCodeAt(index); + // parseInt parses a string to a first unavailable symbol + // but ToNumber should return NaN if a string contains unavailable symbols + if (code < 48 || code > maxCode) return NaN; + } return parseInt(digits, radix); + } + } return +it; + }; + + // `Number` constructor + // https://tc39.es/ecma262/#sec-number-constructor + if (isForced_1(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) { + var NumberWrapper = function Number(value) { + var it = arguments.length < 1 ? 0 : value; + var dummy = this; + return dummy instanceof NumberWrapper + // check on 1..constructor(foo) case + && (BROKEN_CLASSOF ? fails(function () { NumberPrototype.valueOf.call(dummy); }) : classofRaw(dummy) != NUMBER) + ? inheritIfRequired(new NativeNumber(toNumber(it)), dummy, NumberWrapper) : toNumber(it); + }; + for (var keys = descriptors ? getOwnPropertyNames(NativeNumber) : ( + // ES3: + 'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' + + // ES2015 (in case, if modules with ES2015 Number statics required before): + 'EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,' + + 'MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger,' + + // ESNext + 'fromString,range' + ).split(','), j = 0, key; keys.length > j; j++) { + if (has$1(NativeNumber, key = keys[j]) && !has$1(NumberWrapper, key)) { + defineProperty(NumberWrapper, key, getOwnPropertyDescriptor$2(NativeNumber, key)); + } + } + NumberWrapper.prototype = NumberPrototype; + NumberPrototype.constructor = NumberWrapper; + redefine(global_1, NUMBER, NumberWrapper); + } + + var nativeReverse = [].reverse; + var test = [1, 2]; + + // `Array.prototype.reverse` method + // https://tc39.es/ecma262/#sec-array.prototype.reverse + // fix for Safari 12.0 bug + // https://bugs.webkit.org/show_bug.cgi?id=188794 + _export({ target: 'Array', proto: true, forced: String(test) === String(test.reverse()) }, { + reverse: function reverse() { + // eslint-disable-next-line no-self-assign -- dirty hack + if (isArray(this)) this.length = this.length; + return nativeReverse.call(this); + } + }); + + /* eslint-disable no-unused-vars */ + + var VERSION = '1.18.3'; + var bootstrapVersion = 4; + + try { + var rawVersion = $__default['default'].fn.dropdown.Constructor.VERSION; // Only try to parse VERSION if it is defined. + // It is undefined in older versions of Bootstrap (tested with 3.1.1). + + if (rawVersion !== undefined) { + bootstrapVersion = parseInt(rawVersion, 10); + } + } catch (e) {// ignore + } + + try { + // eslint-disable-next-line no-undef + var _rawVersion = bootstrap.Tooltip.VERSION; + + if (_rawVersion !== undefined) { + bootstrapVersion = parseInt(_rawVersion, 10); + } + } catch (e) {// ignore + } + + var CONSTANTS = { + 3: { + iconsPrefix: 'glyphicon', + icons: { + paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', + paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', + refresh: 'glyphicon-refresh icon-refresh', + toggleOff: 'glyphicon-list-alt icon-list-alt', + toggleOn: 'glyphicon-list-alt icon-list-alt', + columns: 'glyphicon-th icon-th', + detailOpen: 'glyphicon-plus icon-plus', + detailClose: 'glyphicon-minus icon-minus', + fullscreen: 'glyphicon-fullscreen', + search: 'glyphicon-search', + clearSearch: 'glyphicon-trash' + }, + classes: { + buttonsPrefix: 'btn', + buttons: 'default', + buttonsGroup: 'btn-group', + buttonsDropdown: 'btn-group', + pull: 'pull', + inputGroup: 'input-group', + inputPrefix: 'input-', + input: 'form-control', + paginationDropdown: 'btn-group dropdown', + dropup: 'dropup', + dropdownActive: 'active', + paginationActive: 'active', + buttonActive: 'active' + }, + html: { + toolbarDropdown: [''], + toolbarDropdownItem: '', + toolbarDropdownSeparator: '
  • ', + pageDropdown: [''], + pageDropdownItem: '
    ', + dropdownCaret: '', + pagination: ['
      ', '
    '], + paginationItem: '
  • %s
  • ', + icon: '', + inputGroup: '
    %s%s
    ', + searchInput: '', + searchButton: '', + searchClearButton: '' + } + }, + 4: { + iconsPrefix: 'fa', + icons: { + paginationSwitchDown: 'fa-caret-square-down', + paginationSwitchUp: 'fa-caret-square-up', + refresh: 'fa-sync', + toggleOff: 'fa-toggle-off', + toggleOn: 'fa-toggle-on', + columns: 'fa-th-list', + detailOpen: 'fa-plus', + detailClose: 'fa-minus', + fullscreen: 'fa-arrows-alt', + search: 'fa-search', + clearSearch: 'fa-trash' + }, + classes: { + buttonsPrefix: 'btn', + buttons: 'secondary', + buttonsGroup: 'btn-group', + buttonsDropdown: 'btn-group', + pull: 'float', + inputGroup: 'btn-group', + inputPrefix: 'form-control-', + input: 'form-control', + paginationDropdown: 'btn-group dropdown', + dropup: 'dropup', + dropdownActive: 'active', + paginationActive: 'active', + buttonActive: 'active' + }, + html: { + toolbarDropdown: [''], + toolbarDropdownItem: '', + pageDropdown: [''], + pageDropdownItem: '%s', + toolbarDropdownSeparator: '', + dropdownCaret: '', + pagination: ['
      ', '
    '], + paginationItem: '
  • %s
  • ', + icon: '', + inputGroup: '
    %s
    %s
    ', + searchInput: '', + searchButton: '', + searchClearButton: '' + } + }, + 5: { + iconsPrefix: 'fa', + icons: { + paginationSwitchDown: 'fa-caret-square-down', + paginationSwitchUp: 'fa-caret-square-up', + refresh: 'fa-sync', + toggleOff: 'fa-toggle-off', + toggleOn: 'fa-toggle-on', + columns: 'fa-th-list', + detailOpen: 'fa-plus', + detailClose: 'fa-minus', + fullscreen: 'fa-arrows-alt', + search: 'fa-search', + clearSearch: 'fa-trash' + }, + classes: { + buttonsPrefix: 'btn', + buttons: 'secondary', + buttonsGroup: 'btn-group', + buttonsDropdown: 'btn-group', + pull: 'float', + inputGroup: 'btn-group', + inputPrefix: 'form-control-', + input: 'form-control', + paginationDropdown: 'btn-group dropdown', + dropup: 'dropup', + dropdownActive: 'active', + paginationActive: 'active', + buttonActive: 'active' + }, + html: { + dataToggle: 'data-bs-toggle', + toolbarDropdown: [''], + toolbarDropdownItem: '', + pageDropdown: [''], + pageDropdownItem: '%s', + toolbarDropdownSeparator: '', + dropdownCaret: '', + pagination: ['
      ', '
    '], + paginationItem: '
  • %s
  • ', + icon: '', + inputGroup: '
    %s
    %s
    ', + searchInput: '', + searchButton: '', + searchClearButton: '' + } + } + }[bootstrapVersion]; + var DEFAULTS = { + height: undefined, + classes: 'table table-bordered table-hover', + buttons: {}, + theadClasses: '', + headerStyle: function headerStyle(column) { + return {}; + }, + rowStyle: function rowStyle(row, index) { + return {}; + }, + rowAttributes: function rowAttributes(row, index) { + return {}; + }, + undefinedText: '-', + locale: undefined, + virtualScroll: false, + virtualScrollItemHeight: undefined, + sortable: true, + sortClass: undefined, + silentSort: true, + sortName: undefined, + sortOrder: undefined, + sortReset: false, + sortStable: false, + rememberOrder: false, + serverSort: true, + customSort: undefined, + columns: [[]], + data: [], + url: undefined, + method: 'get', + cache: true, + contentType: 'application/json', + dataType: 'json', + ajax: undefined, + ajaxOptions: {}, + queryParams: function queryParams(params) { + return params; + }, + queryParamsType: 'limit', + // 'limit', undefined + responseHandler: function responseHandler(res) { + return res; + }, + totalField: 'total', + totalNotFilteredField: 'totalNotFiltered', + dataField: 'rows', + footerField: 'footer', + pagination: false, + paginationParts: ['pageInfo', 'pageSize', 'pageList'], + showExtendedPagination: false, + paginationLoop: true, + sidePagination: 'client', + // client or server + totalRows: 0, + totalNotFiltered: 0, + pageNumber: 1, + pageSize: 10, + pageList: [10, 25, 50, 100], + paginationHAlign: 'right', + // right, left + paginationVAlign: 'bottom', + // bottom, top, both + paginationDetailHAlign: 'left', + // right, left + paginationPreText: '‹', + paginationNextText: '›', + paginationSuccessivelySize: 5, + // Maximum successively number of pages in a row + paginationPagesBySide: 1, + // Number of pages on each side (right, left) of the current page. + paginationUseIntermediate: false, + // Calculate intermediate pages for quick access + search: false, + searchHighlight: false, + searchOnEnterKey: false, + strictSearch: false, + searchSelector: false, + visibleSearch: false, + showButtonIcons: true, + showButtonText: false, + showSearchButton: false, + showSearchClearButton: false, + trimOnSearch: true, + searchAlign: 'right', + searchTimeOut: 500, + searchText: '', + customSearch: undefined, + showHeader: true, + showFooter: false, + footerStyle: function footerStyle(column) { + return {}; + }, + searchAccentNeutralise: false, + showColumns: false, + showColumnsToggleAll: false, + showColumnsSearch: false, + minimumCountColumns: 1, + showPaginationSwitch: false, + showRefresh: false, + showToggle: false, + showFullscreen: false, + smartDisplay: true, + escape: false, + filterOptions: { + filterAlgorithm: 'and' + }, + idField: undefined, + selectItemName: 'btSelectItem', + clickToSelect: false, + ignoreClickToSelectOn: function ignoreClickToSelectOn(_ref) { + var tagName = _ref.tagName; + return ['A', 'BUTTON'].includes(tagName); + }, + singleSelect: false, + checkboxHeader: true, + maintainMetaData: false, + multipleSelectRow: false, + uniqueId: undefined, + cardView: false, + detailView: false, + detailViewIcon: true, + detailViewByClick: false, + detailViewAlign: 'left', + detailFormatter: function detailFormatter(index, row) { + return ''; + }, + detailFilter: function detailFilter(index, row) { + return true; + }, + toolbar: undefined, + toolbarAlign: 'left', + buttonsToolbar: undefined, + buttonsAlign: 'right', + buttonsOrder: ['paginationSwitch', 'refresh', 'toggle', 'fullscreen', 'columns'], + buttonsPrefix: CONSTANTS.classes.buttonsPrefix, + buttonsClass: CONSTANTS.classes.buttons, + icons: CONSTANTS.icons, + iconSize: undefined, + iconsPrefix: CONSTANTS.iconsPrefix, + // glyphicon or fa(font-awesome) + loadingFontSize: 'auto', + loadingTemplate: function loadingTemplate(loadingMessage) { + return "\n ".concat(loadingMessage, "\n \n \n "); + }, + onAll: function onAll(name, args) { + return false; + }, + onClickCell: function onClickCell(field, value, row, $element) { + return false; + }, + onDblClickCell: function onDblClickCell(field, value, row, $element) { + return false; + }, + onClickRow: function onClickRow(item, $element) { + return false; + }, + onDblClickRow: function onDblClickRow(item, $element) { + return false; + }, + onSort: function onSort(name, order) { + return false; + }, + onCheck: function onCheck(row) { + return false; + }, + onUncheck: function onUncheck(row) { + return false; + }, + onCheckAll: function onCheckAll(rows) { + return false; + }, + onUncheckAll: function onUncheckAll(rows) { + return false; + }, + onCheckSome: function onCheckSome(rows) { + return false; + }, + onUncheckSome: function onUncheckSome(rows) { + return false; + }, + onLoadSuccess: function onLoadSuccess(data) { + return false; + }, + onLoadError: function onLoadError(status) { + return false; + }, + onColumnSwitch: function onColumnSwitch(field, checked) { + return false; + }, + onPageChange: function onPageChange(number, size) { + return false; + }, + onSearch: function onSearch(text) { + return false; + }, + onToggle: function onToggle(cardView) { + return false; + }, + onPreBody: function onPreBody(data) { + return false; + }, + onPostBody: function onPostBody() { + return false; + }, + onPostHeader: function onPostHeader() { + return false; + }, + onPostFooter: function onPostFooter() { + return false; + }, + onExpandRow: function onExpandRow(index, row, $detail) { + return false; + }, + onCollapseRow: function onCollapseRow(index, row) { + return false; + }, + onRefreshOptions: function onRefreshOptions(options) { + return false; + }, + onRefresh: function onRefresh(params) { + return false; + }, + onResetView: function onResetView() { + return false; + }, + onScrollBody: function onScrollBody() { + return false; + } + }; + var EN = { + formatLoadingMessage: function formatLoadingMessage() { + return 'Loading, please wait'; + }, + formatRecordsPerPage: function formatRecordsPerPage(pageNumber) { + return "".concat(pageNumber, " rows per page"); + }, + formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) { + if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) { + return "Showing ".concat(pageFrom, " to ").concat(pageTo, " of ").concat(totalRows, " rows (filtered from ").concat(totalNotFiltered, " total rows)"); + } + + return "Showing ".concat(pageFrom, " to ").concat(pageTo, " of ").concat(totalRows, " rows"); + }, + formatSRPaginationPreText: function formatSRPaginationPreText() { + return 'previous page'; + }, + formatSRPaginationPageText: function formatSRPaginationPageText(page) { + return "to page ".concat(page); + }, + formatSRPaginationNextText: function formatSRPaginationNextText() { + return 'next page'; + }, + formatDetailPagination: function formatDetailPagination(totalRows) { + return "Showing ".concat(totalRows, " rows"); + }, + formatSearch: function formatSearch() { + return 'Search'; + }, + formatClearSearch: function formatClearSearch() { + return 'Clear Search'; + }, + formatNoMatches: function formatNoMatches() { + return 'No matching records found'; + }, + formatPaginationSwitch: function formatPaginationSwitch() { + return 'Hide/Show pagination'; + }, + formatPaginationSwitchDown: function formatPaginationSwitchDown() { + return 'Show pagination'; + }, + formatPaginationSwitchUp: function formatPaginationSwitchUp() { + return 'Hide pagination'; + }, + formatRefresh: function formatRefresh() { + return 'Refresh'; + }, + formatToggle: function formatToggle() { + return 'Toggle'; + }, + formatToggleOn: function formatToggleOn() { + return 'Show card view'; + }, + formatToggleOff: function formatToggleOff() { + return 'Hide card view'; + }, + formatColumns: function formatColumns() { + return 'Columns'; + }, + formatColumnsToggleAll: function formatColumnsToggleAll() { + return 'Toggle all'; + }, + formatFullscreen: function formatFullscreen() { + return 'Fullscreen'; + }, + formatAllRows: function formatAllRows() { + return 'All'; + } + }; + var COLUMN_DEFAULTS = { + field: undefined, + title: undefined, + titleTooltip: undefined, + class: undefined, + width: undefined, + widthUnit: 'px', + rowspan: undefined, + colspan: undefined, + align: undefined, + // left, right, center + halign: undefined, + // left, right, center + falign: undefined, + // left, right, center + valign: undefined, + // top, middle, bottom + cellStyle: undefined, + radio: false, + checkbox: false, + checkboxEnabled: true, + clickToSelect: true, + showSelectTitle: false, + sortable: false, + sortName: undefined, + order: 'asc', + // asc, desc + sorter: undefined, + visible: true, + switchable: true, + cardVisible: true, + searchable: true, + formatter: undefined, + footerFormatter: undefined, + detailFormatter: undefined, + searchFormatter: true, + searchHighlightFormatter: false, + escape: false, + events: undefined + }; + var METHODS = ['getOptions', 'refreshOptions', 'getData', 'getSelections', 'load', 'append', 'prepend', 'remove', 'removeAll', 'insertRow', 'updateRow', 'getRowByUniqueId', 'updateByUniqueId', 'removeByUniqueId', 'updateCell', 'updateCellByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', 'showColumn', 'hideColumn', 'getVisibleColumns', 'getHiddenColumns', 'showAllColumns', 'hideAllColumns', 'mergeCells', 'checkAll', 'uncheckAll', 'checkInvert', 'check', 'uncheck', 'checkBy', 'uncheckBy', 'refresh', 'destroy', 'resetView', 'showLoading', 'hideLoading', 'togglePagination', 'toggleFullscreen', 'toggleView', 'resetSearch', 'filterBy', 'scrollTo', 'getScrollPosition', 'selectPage', 'prevPage', 'nextPage', 'toggleDetailView', 'expandRow', 'collapseRow', 'expandRowByUniqueId', 'collapseRowByUniqueId', 'expandAllRows', 'collapseAllRows', 'updateColumnTitle', 'updateFormatText']; + var EVENTS = { + 'all.bs.table': 'onAll', + 'click-row.bs.table': 'onClickRow', + 'dbl-click-row.bs.table': 'onDblClickRow', + 'click-cell.bs.table': 'onClickCell', + 'dbl-click-cell.bs.table': 'onDblClickCell', + 'sort.bs.table': 'onSort', + 'check.bs.table': 'onCheck', + 'uncheck.bs.table': 'onUncheck', + 'check-all.bs.table': 'onCheckAll', + 'uncheck-all.bs.table': 'onUncheckAll', + 'check-some.bs.table': 'onCheckSome', + 'uncheck-some.bs.table': 'onUncheckSome', + 'load-success.bs.table': 'onLoadSuccess', + 'load-error.bs.table': 'onLoadError', + 'column-switch.bs.table': 'onColumnSwitch', + 'page-change.bs.table': 'onPageChange', + 'search.bs.table': 'onSearch', + 'toggle.bs.table': 'onToggle', + 'pre-body.bs.table': 'onPreBody', + 'post-body.bs.table': 'onPostBody', + 'post-header.bs.table': 'onPostHeader', + 'post-footer.bs.table': 'onPostFooter', + 'expand-row.bs.table': 'onExpandRow', + 'collapse-row.bs.table': 'onCollapseRow', + 'refresh-options.bs.table': 'onRefreshOptions', + 'reset-view.bs.table': 'onResetView', + 'refresh.bs.table': 'onRefresh', + 'scroll-body.bs.table': 'onScrollBody' + }; + Object.assign(DEFAULTS, EN); + var Constants = { + VERSION: VERSION, + THEME: "bootstrap".concat(bootstrapVersion), + CONSTANTS: CONSTANTS, + DEFAULTS: DEFAULTS, + COLUMN_DEFAULTS: COLUMN_DEFAULTS, + METHODS: METHODS, + EVENTS: EVENTS, + LOCALES: { + en: EN, + 'en-US': EN + } + }; + + var FAILS_ON_PRIMITIVES = fails(function () { objectKeys(1); }); + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + _export({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES }, { + keys: function keys(it) { + return objectKeys(toObject(it)); + } + }); + + var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f; + + + + + + + var nativeStartsWith = ''.startsWith; + var min$1 = Math.min; + + var CORRECT_IS_REGEXP_LOGIC$1 = correctIsRegexpLogic('startsWith'); + // https://github.com/zloirock/core-js/pull/702 + var MDN_POLYFILL_BUG$1 = !CORRECT_IS_REGEXP_LOGIC$1 && !!function () { + var descriptor = getOwnPropertyDescriptor$1(String.prototype, 'startsWith'); + return descriptor && !descriptor.writable; + }(); + + // `String.prototype.startsWith` method + // https://tc39.es/ecma262/#sec-string.prototype.startswith + _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG$1 && !CORRECT_IS_REGEXP_LOGIC$1 }, { + startsWith: function startsWith(searchString /* , position = 0 */) { + var that = String(requireObjectCoercible(this)); + notARegexp(searchString); + var index = toLength(min$1(arguments.length > 1 ? arguments[1] : undefined, that.length)); + var search = String(searchString); + return nativeStartsWith + ? nativeStartsWith.call(that, search, index) + : that.slice(index, index + search.length) === search; + } + }); + + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + + + + + + + var nativeEndsWith = ''.endsWith; + var min = Math.min; + + var CORRECT_IS_REGEXP_LOGIC = correctIsRegexpLogic('endsWith'); + // https://github.com/zloirock/core-js/pull/702 + var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () { + var descriptor = getOwnPropertyDescriptor(String.prototype, 'endsWith'); + return descriptor && !descriptor.writable; + }(); + + // `String.prototype.endsWith` method + // https://tc39.es/ecma262/#sec-string.prototype.endswith + _export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, { + endsWith: function endsWith(searchString /* , endPosition = @length */) { + var that = String(requireObjectCoercible(this)); + notARegexp(searchString); + var endPosition = arguments.length > 1 ? arguments[1] : undefined; + var len = toLength(that.length); + var end = endPosition === undefined ? len : min(toLength(endPosition), len); + var search = String(searchString); + return nativeEndsWith + ? nativeEndsWith.call(that, search, end) + : that.slice(end - search.length, end) === search; + } + }); + + var Utils = { + getSearchInput: function getSearchInput(that) { + if (typeof that.options.searchSelector === 'string') { + return $__default['default'](that.options.searchSelector); + } + + return that.$toolbar.find('.search input'); + }, + // it only does '%s', and return '' when arguments are undefined + sprintf: function sprintf(_str) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var flag = true; + var i = 0; + + var str = _str.replace(/%s/g, function () { + var arg = args[i++]; + + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + + return arg; + }); + + return flag ? str : ''; + }, + isObject: function isObject(val) { + return val instanceof Object && !Array.isArray(val); + }, + isEmptyObject: function isEmptyObject() { + var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return Object.entries(obj).length === 0 && obj.constructor === Object; + }, + isNumeric: function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }, + getFieldTitle: function getFieldTitle(list, value) { + var _iterator = _createForOfIteratorHelper(list), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var item = _step.value; if (item.field === value) { return item.title; } } - return ''; - }, - setFieldIndex: function setFieldIndex(columns) { - var totalCol = 0; - var flag = []; + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } - for (var _iterator2 = columns[0], _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { - var _ref2; + return ''; + }, + setFieldIndex: function setFieldIndex(columns) { + var totalCol = 0; + var flag = []; - if (_isArray2) { - if (_i2 >= _iterator2.length) break; - _ref2 = _iterator2[_i2++]; - } else { - _i2 = _iterator2.next(); - if (_i2.done) break; - _ref2 = _i2.value; - } - - var column = _ref2; + var _iterator2 = _createForOfIteratorHelper(columns[0]), + _step2; + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var column = _step2.value; totalCol += column.colspan || 1; } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); + } - for (var i = 0; i < columns.length; i++) { - flag[i] = []; - for (var j = 0; j < totalCol; j++) { - flag[i][j] = false; - } + for (var i = 0; i < columns.length; i++) { + flag[i] = []; + + for (var j = 0; j < totalCol; j++) { + flag[i][j] = false; } + } - for (var _i3 = 0; _i3 < columns.length; _i3++) { - for (var _iterator3 = columns[_i3], _isArray3 = Array.isArray(_iterator3), _i4 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { - var _ref3; - - if (_isArray3) { - if (_i4 >= _iterator3.length) break; - _ref3 = _iterator3[_i4++]; - } else { - _i4 = _iterator3.next(); - if (_i4.done) break; - _ref3 = _i4.value; - } - - var r = _ref3; + for (var _i = 0; _i < columns.length; _i++) { + var _iterator3 = _createForOfIteratorHelper(columns[_i]), + _step3; + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var r = _step3.value; var rowspan = r.rowspan || 1; var colspan = r.colspan || 1; - var index = flag[_i3].indexOf(false); + + var index = flag[_i].indexOf(false); + + r.colspanIndex = index; if (colspan === 1) { - r.fieldIndex = index; - // when field is undefined, use index instead + r.fieldIndex = index; // when field is undefined, use index instead + if (typeof r.field === 'undefined') { r.field = index; } + } else { + r.colspanGroup = r.colspan; } - for (var k = 0; k < rowspan; k++) { - flag[_i3 + k][index] = true; - } - for (var _k = 0; _k < colspan; _k++) { - flag[_i3][index + _k] = true; - } - } - } - }, - getScrollBarWidth: function getScrollBarWidth() { - if (this.cachedWidth === undefined) { - var $inner = $('
    ').addClass('fixed-table-scroll-inner'); - var $outer = $('
    ').addClass('fixed-table-scroll-outer'); - - $outer.append($inner); - $('body').append($outer); - - var w1 = $inner[0].offsetWidth; - $outer.css('overflow', 'scroll'); - var w2 = $inner[0].offsetWidth; - - if (w1 === w2) { - w2 = $outer[0].clientWidth; - } - - $outer.remove(); - this.cachedWidth = w1 - w2; - } - return this.cachedWidth; - }, - calculateObjectValue: function calculateObjectValue(self, name, args, defaultValue) { - var func = name; - - if (typeof name === 'string') { - // support obj.func1.func2 - var names = name.split('.'); - - if (names.length > 1) { - func = window; - for (var _iterator4 = names, _isArray4 = Array.isArray(_iterator4), _i5 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { - var _ref4; - - if (_isArray4) { - if (_i5 >= _iterator4.length) break; - _ref4 = _iterator4[_i5++]; - } else { - _i5 = _iterator4.next(); - if (_i5.done) break; - _ref4 = _i5.value; + for (var _j = 0; _j < rowspan; _j++) { + for (var k = 0; k < colspan; k++) { + flag[_i + _j][index + k] = true; } + } + } + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); + } + } + }, + normalizeAccent: function normalizeAccent(value) { + if (typeof value !== 'string') { + return value; + } - var f = _ref4; + return value.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); + }, + updateFieldGroup: function updateFieldGroup(columns) { + var _ref; + var allColumns = (_ref = []).concat.apply(_ref, _toConsumableArray(columns)); + + var _iterator4 = _createForOfIteratorHelper(columns), + _step4; + + try { + for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { + var c = _step4.value; + + var _iterator5 = _createForOfIteratorHelper(c), + _step5; + + try { + for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { + var r = _step5.value; + + if (r.colspanGroup > 1) { + var colspan = 0; + + var _loop = function _loop(i) { + var column = allColumns.find(function (col) { + return col.fieldIndex === i; + }); + + if (column.visible) { + colspan++; + } + }; + + for (var i = r.colspanIndex; i < r.colspanIndex + r.colspanGroup; i++) { + _loop(i); + } + + r.colspan = colspan; + r.visible = colspan > 0; + } + } + } catch (err) { + _iterator5.e(err); + } finally { + _iterator5.f(); + } + } + } catch (err) { + _iterator4.e(err); + } finally { + _iterator4.f(); + } + }, + getScrollBarWidth: function getScrollBarWidth() { + if (this.cachedWidth === undefined) { + var $inner = $__default['default']('
    ').addClass('fixed-table-scroll-inner'); + var $outer = $__default['default']('
    ').addClass('fixed-table-scroll-outer'); + $outer.append($inner); + $__default['default']('body').append($outer); + var w1 = $inner[0].offsetWidth; + $outer.css('overflow', 'scroll'); + var w2 = $inner[0].offsetWidth; + + if (w1 === w2) { + w2 = $outer[0].clientWidth; + } + + $outer.remove(); + this.cachedWidth = w1 - w2; + } + + return this.cachedWidth; + }, + calculateObjectValue: function calculateObjectValue(self, name, args, defaultValue) { + var func = name; + + if (typeof name === 'string') { + // support obj.func1.func2 + var names = name.split('.'); + + if (names.length > 1) { + func = window; + + var _iterator6 = _createForOfIteratorHelper(names), + _step6; + + try { + for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { + var f = _step6.value; func = func[f]; } - } else { - func = window[name]; + } catch (err) { + _iterator6.e(err); + } finally { + _iterator6.f(); } + } else { + func = window[name]; } + } - if (func !== null && (typeof func === 'undefined' ? 'undefined' : _typeof(func)) === 'object') { - return func; - } + if (func !== null && _typeof(func) === 'object') { + return func; + } - if (typeof func === 'function') { - return func.apply(self, args || []); - } + if (typeof func === 'function') { + return func.apply(self, args || []); + } - if (!func && typeof name === 'string' && this.sprintf.apply(this, [name].concat(_toConsumableArray(args)))) { - return this.sprintf.apply(this, [name].concat(_toConsumableArray(args))); - } + if (!func && typeof name === 'string' && this.sprintf.apply(this, [name].concat(_toConsumableArray(args)))) { + return this.sprintf.apply(this, [name].concat(_toConsumableArray(args))); + } - return defaultValue; - }, - compareObjects: function compareObjects(objectA, objectB, compareLength) { - var aKeys = Object.keys(objectA); - var bKeys = Object.keys(objectB); + return defaultValue; + }, + compareObjects: function compareObjects(objectA, objectB, compareLength) { + var aKeys = Object.keys(objectA); + var bKeys = Object.keys(objectB); - if (compareLength && aKeys.length !== bKeys.length) { + if (compareLength && aKeys.length !== bKeys.length) { + return false; + } + + for (var _i2 = 0, _aKeys = aKeys; _i2 < _aKeys.length; _i2++) { + var key = _aKeys[_i2]; + + if (bKeys.includes(key) && objectA[key] !== objectB[key]) { return false; } + } - for (var _iterator5 = aKeys, _isArray5 = Array.isArray(_iterator5), _i6 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { - var _ref5; + return true; + }, + escapeHTML: function escapeHTML(text) { + if (typeof text === 'string') { + return text.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/`/g, '`'); + } - if (_isArray5) { - if (_i6 >= _iterator5.length) break; - _ref5 = _iterator5[_i6++]; - } else { - _i6 = _iterator5.next(); - if (_i6.done) break; - _ref5 = _i6.value; - } + return text; + }, + unescapeHTML: function unescapeHTML(text) { + if (typeof text === 'string') { + return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, '\'').replace(/`/g, '`'); + } - var key = _ref5; + return text; + }, + getRealDataAttr: function getRealDataAttr(dataAttr) { + for (var _i3 = 0, _Object$entries = Object.entries(dataAttr); _i3 < _Object$entries.length; _i3++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2), + attr = _Object$entries$_i[0], + value = _Object$entries$_i[1]; - if (bKeys.indexOf(key) !== -1 && objectA[key] !== objectB[key]) { - return false; - } + var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase(); + + if (auxAttr !== attr) { + dataAttr[auxAttr] = value; + delete dataAttr[attr]; } + } - return true; - }, - escapeHTML: function escapeHTML(text) { - if (typeof text === 'string') { - return text.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/`/g, '`'); - } - return text; - }, - getRealDataAttr: function getRealDataAttr(dataAttr) { - for (var _iterator6 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(dataAttr), _isArray6 = Array.isArray(_iterator6), _i7 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { - var _ref6; + return dataAttr; + }, + getItemField: function getItemField(item, field, escape) { + var value = item; - if (_isArray6) { - if (_i7 >= _iterator6.length) break; - _ref6 = _iterator6[_i7++]; - } else { - _i7 = _iterator6.next(); - if (_i7.done) break; - _ref6 = _i7.value; - } + if (typeof field !== 'string' || item.hasOwnProperty(field)) { + return escape ? this.escapeHTML(item[field]) : item[field]; + } - var _ref7 = _ref6, - _ref8 = _slicedToArray(_ref7, 2), - attr = _ref8[0], - value = _ref8[1]; + var props = field.split('.'); - var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase(); - if (auxAttr !== attr) { - dataAttr[auxAttr] = value; - delete dataAttr[attr]; - } - } - return dataAttr; - }, - getItemField: function getItemField(item, field, escape) { - var value = item; - - if (typeof field !== 'string' || item.hasOwnProperty(field)) { - return escape ? this.escapeHTML(item[field]) : item[field]; - } - - var props = field.split('.'); - for (var _iterator7 = props, _isArray7 = Array.isArray(_iterator7), _i8 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { - var _ref9; - - if (_isArray7) { - if (_i8 >= _iterator7.length) break; - _ref9 = _iterator7[_i8++]; - } else { - _i8 = _iterator7.next(); - if (_i8.done) break; - _ref9 = _i8.value; - } - - var p = _ref9; + var _iterator7 = _createForOfIteratorHelper(props), + _step7; + try { + for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { + var p = _step7.value; value = value && value[p]; } - return escape ? this.escapeHTML(value) : value; - }, - isIEBrowser: function isIEBrowser() { - return navigator.userAgent.indexOf('MSIE ') !== -1 || /Trident.*rv:11\./.test(navigator.userAgent); - }, - findIndex: function findIndex(items, item) { - for (var _iterator8 = items, _isArray8 = Array.isArray(_iterator8), _i9 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { - var _ref10; + } catch (err) { + _iterator7.e(err); + } finally { + _iterator7.f(); + } - if (_isArray8) { - if (_i9 >= _iterator8.length) break; - _ref10 = _iterator8[_i9++]; - } else { - _i9 = _iterator8.next(); - if (_i9.done) break; - _ref10 = _i9.value; - } + return escape ? this.escapeHTML(value) : value; + }, + isIEBrowser: function isIEBrowser() { + return navigator.userAgent.includes('MSIE ') || /Trident.*rv:11\./.test(navigator.userAgent); + }, + findIndex: function findIndex(items, item) { + var _iterator8 = _createForOfIteratorHelper(items), + _step8; - var it = _ref10; + try { + for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { + var it = _step8.value; if (JSON.stringify(it) === JSON.stringify(item)) { return items.indexOf(it); } } - return -1; - } - }; - - // BOOTSTRAP TABLE CLASS DEFINITION - // ====================== - - var DEFAULTS = { - height: undefined, - classes: 'table table-bordered table-hover', - theadClasses: '', - rowStyle: function rowStyle(row, index) { - return {}; - }, - rowAttributes: function rowAttributes(row, index) { - return {}; - }, - - undefinedText: '-', - locale: undefined, - sortable: true, - sortClass: undefined, - silentSort: true, - sortName: undefined, - sortOrder: 'asc', - sortStable: false, - rememberOrder: false, - customSort: undefined, - columns: [[]], - data: [], - url: undefined, - method: 'get', - cache: true, - contentType: 'application/json', - dataType: 'json', - ajax: undefined, - ajaxOptions: {}, - queryParams: function queryParams(params) { - return params; - }, - - queryParamsType: 'limit', responseHandler: function responseHandler(res) { - return res; - }, - - totalField: 'total', - dataField: 'rows', - pagination: false, - onlyInfoPagination: false, - paginationLoop: true, - sidePagination: 'client', // client or server - totalRows: 0, - pageNumber: 1, - pageSize: 10, - pageList: [10, 25, 50, 100], - paginationHAlign: 'right', // right, left - paginationVAlign: 'bottom', // bottom, top, both - paginationDetailHAlign: 'left', // right, left - paginationPreText: '‹', - paginationNextText: '›', - paginationSuccessivelySize: 5, // Maximum successively number of pages in a row - paginationPagesBySide: 1, // Number of pages on each side (right, left) of the current page. - paginationUseIntermediate: false, // Calculate intermediate pages for quick access - search: false, - searchOnEnterKey: false, - strictSearch: false, - trimOnSearch: true, - searchAlign: 'right', - searchTimeOut: 500, - searchText: '', - customSearch: undefined, - showHeader: true, - showFooter: false, - footerStyle: function footerStyle(row, index) { - return {}; - }, - - showColumns: false, - minimumCountColumns: 1, - showPaginationSwitch: false, - showRefresh: false, - showToggle: false, - showFullscreen: false, - smartDisplay: true, - escape: false, - idField: undefined, - selectItemName: 'btSelectItem', - clickToSelect: false, - ignoreClickToSelectOn: function ignoreClickToSelectOn(_ref11) { - var tagName = _ref11.tagName; - - return ['A', 'BUTTON'].indexOf(tagName) !== -1; - }, - - singleSelect: false, - checkboxHeader: true, - maintainSelected: false, - uniqueId: undefined, - cardView: false, - detailView: false, - detailFormatter: function detailFormatter(index, row) { - return ''; - }, - detailFilter: function detailFilter(index, row) { - return true; - }, - - toolbar: undefined, - toolbarAlign: 'left', - buttonsToolbar: undefined, - buttonsAlign: 'right', - buttonsPrefix: constants.classes.buttonsPrefix, - buttonsClass: constants.classes.buttons, - icons: constants.icons, - iconSize: undefined, - iconsPrefix: constants.iconsPrefix, onAll: function onAll(name, args) { - return false; - }, - onClickCell: function onClickCell(field, value, row, $element) { - return false; - }, - onDblClickCell: function onDblClickCell(field, value, row, $element) { - return false; - }, - onClickRow: function onClickRow(item, $element) { - return false; - }, - onDblClickRow: function onDblClickRow(item, $element) { - return false; - }, - onSort: function onSort(name, order) { - return false; - }, - onCheck: function onCheck(row) { - return false; - }, - onUncheck: function onUncheck(row) { - return false; - }, - onCheckAll: function onCheckAll(rows) { - return false; - }, - onUncheckAll: function onUncheckAll(rows) { - return false; - }, - onCheckSome: function onCheckSome(rows) { - return false; - }, - onUncheckSome: function onUncheckSome(rows) { - return false; - }, - onLoadSuccess: function onLoadSuccess(data) { - return false; - }, - onLoadError: function onLoadError(status) { - return false; - }, - onColumnSwitch: function onColumnSwitch(field, checked) { - return false; - }, - onPageChange: function onPageChange(number, size) { - return false; - }, - onSearch: function onSearch(text) { - return false; - }, - onToggle: function onToggle(cardView) { - return false; - }, - onPreBody: function onPreBody(data) { - return false; - }, - onPostBody: function onPostBody() { - return false; - }, - onPostHeader: function onPostHeader() { - return false; - }, - onExpandRow: function onExpandRow(index, row, $detail) { - return false; - }, - onCollapseRow: function onCollapseRow(index, row) { - return false; - }, - onRefreshOptions: function onRefreshOptions(options) { - return false; - }, - onRefresh: function onRefresh(params) { - return false; - }, - onResetView: function onResetView() { - return false; - }, - onScrollBody: function onScrollBody() { - return false; - } - }; - - var LOCALES = {}; - LOCALES['en-US'] = LOCALES.en = { - formatLoadingMessage: function formatLoadingMessage() { - return 'Loading, please wait'; - }, - formatRecordsPerPage: function formatRecordsPerPage(pageNumber) { - return pageNumber + ' rows per page'; - }, - formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows) { - return 'Showing ' + pageFrom + ' to ' + pageTo + ' of ' + totalRows + ' rows'; - }, - formatDetailPagination: function formatDetailPagination(totalRows) { - return 'Showing ' + totalRows + ' rows'; - }, - formatSearch: function formatSearch() { - return 'Search'; - }, - formatNoMatches: function formatNoMatches() { - return 'No matching records found'; - }, - formatPaginationSwitch: function formatPaginationSwitch() { - return 'Hide/Show pagination'; - }, - formatRefresh: function formatRefresh() { - return 'Refresh'; - }, - formatToggle: function formatToggle() { - return 'Toggle'; - }, - formatColumns: function formatColumns() { - return 'Columns'; - }, - formatFullscreen: function formatFullscreen() { - return 'Fullscreen'; - }, - formatAllRows: function formatAllRows() { - return 'All'; - } - }; - - $.extend(DEFAULTS, LOCALES['en-US']); - - var COLUMN_DEFAULTS = { - radio: false, - checkbox: false, - checkboxEnabled: true, - field: undefined, - title: undefined, - titleTooltip: undefined, - 'class': undefined, - align: undefined, // left, right, center - halign: undefined, // left, right, center - falign: undefined, // left, right, center - valign: undefined, // top, middle, bottom - width: undefined, - sortable: false, - order: 'asc', // asc, desc - visible: true, - switchable: true, - clickToSelect: true, - formatter: undefined, - footerFormatter: undefined, - events: undefined, - sorter: undefined, - sortName: undefined, - cellStyle: undefined, - searchable: true, - searchFormatter: true, - cardVisible: true, - escape: false, - showSelectTitle: false - }; - - var EVENTS = { - 'all.bs.table': 'onAll', - 'click-cell.bs.table': 'onClickCell', - 'dbl-click-cell.bs.table': 'onDblClickCell', - 'click-row.bs.table': 'onClickRow', - 'dbl-click-row.bs.table': 'onDblClickRow', - 'sort.bs.table': 'onSort', - 'check.bs.table': 'onCheck', - 'uncheck.bs.table': 'onUncheck', - 'check-all.bs.table': 'onCheckAll', - 'uncheck-all.bs.table': 'onUncheckAll', - 'check-some.bs.table': 'onCheckSome', - 'uncheck-some.bs.table': 'onUncheckSome', - 'load-success.bs.table': 'onLoadSuccess', - 'load-error.bs.table': 'onLoadError', - 'column-switch.bs.table': 'onColumnSwitch', - 'page-change.bs.table': 'onPageChange', - 'search.bs.table': 'onSearch', - 'toggle.bs.table': 'onToggle', - 'pre-body.bs.table': 'onPreBody', - 'post-body.bs.table': 'onPostBody', - 'post-header.bs.table': 'onPostHeader', - 'expand-row.bs.table': 'onExpandRow', - 'collapse-row.bs.table': 'onCollapseRow', - 'refresh-options.bs.table': 'onRefreshOptions', - 'reset-view.bs.table': 'onResetView', - 'refresh.bs.table': 'onRefresh', - 'scroll-body.bs.table': 'onScrollBody' - }; - - var BootstrapTable = function () { - function BootstrapTable(el, options) { - _classCallCheck(this, BootstrapTable); - - this.options = options; - this.$el = $(el); - this.$el_ = this.$el.clone(); - this.timeoutId_ = 0; - this.timeoutFooter_ = 0; - - this.init(); + } catch (err) { + _iterator8.e(err); + } finally { + _iterator8.f(); } - _createClass(BootstrapTable, [{ - key: 'init', - value: function init() { - this.initConstants(); - this.initLocale(); - this.initContainer(); - this.initTable(); - this.initHeader(); - this.initData(); - this.initHiddenRows(); - this.initFooter(); - this.initToolbar(); - this.initPagination(); - this.initBody(); - this.initSearchText(); - this.initServer(); - } - }, { - key: 'initConstants', - value: function initConstants() { - var o = this.options; - this.constants = constants; + return -1; + }, + trToData: function trToData(columns, $els) { + var _this = this; - var buttonsPrefix = o.buttonsPrefix ? o.buttonsPrefix + '-' : ''; - this.constants.buttonsClass = [o.buttonsPrefix, buttonsPrefix + o.buttonsClass, Utils.sprintf(buttonsPrefix + '%s', o.iconSize)].join(' ').trim(); - } - }, { - key: 'initLocale', - value: function initLocale() { - if (this.options.locale) { - var locales = $.fn.bootstrapTable.locales; - var parts = this.options.locale.split(/-|_/); + var data = []; + var m = []; + $els.each(function (y, el) { + var $el = $__default['default'](el); + var row = {}; // save tr's id, class and data-* attributes - parts[0] = parts[0].toLowerCase(); - if (parts[1]) { - parts[1] = parts[1].toUpperCase(); + row._id = $el.attr('id'); + row._class = $el.attr('class'); + row._data = _this.getRealDataAttr($el.data()); + row._style = $el.attr('style'); + $el.find('>td,>th').each(function (_x, el) { + var $el = $__default['default'](el); + var cspan = +$el.attr('colspan') || 1; + var rspan = +$el.attr('rowspan') || 1; + var x = _x; // skip already occupied cells in current row + + for (; m[y] && m[y][x]; x++) {// ignore + } // mark matrix elements occupied by current cell with true + + + for (var tx = x; tx < x + cspan; tx++) { + for (var ty = y; ty < y + rspan; ty++) { + if (!m[ty]) { + // fill missing rows + m[ty] = []; + } + + m[ty][tx] = true; } + } - if (locales[this.options.locale]) { - $.extend(this.options, locales[this.options.locale]); - } else if (locales[parts.join('-')]) { - $.extend(this.options, locales[parts.join('-')]); - } else if (locales[parts[0]]) { - $.extend(this.options, locales[parts[0]]); + var field = columns[x].field; + row[field] = $el.html().trim(); // save td's id, class and data-* attributes + + row["_".concat(field, "_id")] = $el.attr('id'); + row["_".concat(field, "_class")] = $el.attr('class'); + row["_".concat(field, "_rowspan")] = $el.attr('rowspan'); + row["_".concat(field, "_colspan")] = $el.attr('colspan'); + row["_".concat(field, "_title")] = $el.attr('title'); + row["_".concat(field, "_data")] = _this.getRealDataAttr($el.data()); + row["_".concat(field, "_style")] = $el.attr('style'); + }); + data.push(row); + }); + return data; + }, + sort: function sort(a, b, order, sortStable, aPosition, bPosition) { + if (a === undefined || a === null) { + a = ''; + } + + if (b === undefined || b === null) { + b = ''; + } + + if (sortStable && a === b) { + a = aPosition; + b = bPosition; + } // If both values are numeric, do a numeric comparison + + + if (this.isNumeric(a) && this.isNumeric(b)) { + // Convert numerical values form string to float. + a = parseFloat(a); + b = parseFloat(b); + + if (a < b) { + return order * -1; + } + + if (a > b) { + return order; + } + + return 0; + } + + if (a === b) { + return 0; + } // If value is not a string, convert to string + + + if (typeof a !== 'string') { + a = a.toString(); + } + + if (a.localeCompare(b) === -1) { + return order * -1; + } + + return order; + }, + getEventName: function getEventName(eventPrefix) { + var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + id = id || "".concat(+new Date()).concat(~~(Math.random() * 1000000)); + return "".concat(eventPrefix, "-").concat(id); + }, + hasDetailViewIcon: function hasDetailViewIcon(options) { + return options.detailView && options.detailViewIcon && !options.cardView; + }, + getDetailViewIndexOffset: function getDetailViewIndexOffset(options) { + return this.hasDetailViewIcon(options) && options.detailViewAlign !== 'right' ? 1 : 0; + }, + checkAutoMergeCells: function checkAutoMergeCells(data) { + var _iterator9 = _createForOfIteratorHelper(data), + _step9; + + try { + for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { + var row = _step9.value; + + for (var _i4 = 0, _Object$keys = Object.keys(row); _i4 < _Object$keys.length; _i4++) { + var key = _Object$keys[_i4]; + + if (key.startsWith('_') && (key.endsWith('_rowspan') || key.endsWith('_colspan'))) { + return true; } } } - }, { - key: 'initContainer', - value: function initContainer() { - var topPagination = ['top', 'both'].indexOf(this.options.paginationVAlign) !== -1 ? '
    ' : ''; - var bottomPagination = ['bottom', 'both'].indexOf(this.options.paginationVAlign) !== -1 ? '
    ' : ''; + } catch (err) { + _iterator9.e(err); + } finally { + _iterator9.f(); + } - this.$container = $('\n
    \n
    \n ' + topPagination + '\n
    \n
    \n
    \n
    \n \n ' + this.options.formatLoadingMessage() + '\n \n \n
    \n
    \n \n
    \n ' + bottomPagination + '\n
    \n '); + return false; + }, + deepCopy: function deepCopy(arg) { + if (arg === undefined) { + return arg; + } + + return $__default['default'].extend(true, Array.isArray(arg) ? [] : {}, arg); + } + }; + + var BLOCK_ROWS = 50; + var CLUSTER_BLOCKS = 4; + + var VirtualScroll = /*#__PURE__*/function () { + function VirtualScroll(options) { + var _this = this; + + _classCallCheck(this, VirtualScroll); + + this.rows = options.rows; + this.scrollEl = options.scrollEl; + this.contentEl = options.contentEl; + this.callback = options.callback; + this.itemHeight = options.itemHeight; + this.cache = {}; + this.scrollTop = this.scrollEl.scrollTop; + this.initDOM(this.rows, options.fixedScroll); + this.scrollEl.scrollTop = this.scrollTop; + this.lastCluster = 0; + + var onScroll = function onScroll() { + if (_this.lastCluster !== (_this.lastCluster = _this.getNum())) { + _this.initDOM(_this.rows); + + _this.callback(); + } + }; + + this.scrollEl.addEventListener('scroll', onScroll, false); + + this.destroy = function () { + _this.contentEl.innerHtml = ''; + + _this.scrollEl.removeEventListener('scroll', onScroll, false); + }; + } + + _createClass(VirtualScroll, [{ + key: "initDOM", + value: function initDOM(rows, fixedScroll) { + if (typeof this.clusterHeight === 'undefined') { + this.cache.scrollTop = this.scrollEl.scrollTop; + this.cache.data = this.contentEl.innerHTML = rows[0] + rows[0] + rows[0]; + this.getRowsHeight(rows); + } + + var data = this.initData(rows, this.getNum(fixedScroll)); + var thisRows = data.rows.join(''); + var dataChanged = this.checkChanges('data', thisRows); + var topOffsetChanged = this.checkChanges('top', data.topOffset); + var bottomOffsetChanged = this.checkChanges('bottom', data.bottomOffset); + var html = []; + + if (dataChanged && topOffsetChanged) { + if (data.topOffset) { + html.push(this.getExtra('top', data.topOffset)); + } + + html.push(thisRows); + + if (data.bottomOffset) { + html.push(this.getExtra('bottom', data.bottomOffset)); + } + + this.contentEl.innerHTML = html.join(''); + + if (fixedScroll) { + this.contentEl.scrollTop = this.cache.scrollTop; + } + } else if (bottomOffsetChanged) { + this.contentEl.lastChild.style.height = "".concat(data.bottomOffset, "px"); + } + } + }, { + key: "getRowsHeight", + value: function getRowsHeight() { + if (typeof this.itemHeight === 'undefined') { + var nodes = this.contentEl.children; + var node = nodes[Math.floor(nodes.length / 2)]; + this.itemHeight = node.offsetHeight; + } + + this.blockHeight = this.itemHeight * BLOCK_ROWS; + this.clusterRows = BLOCK_ROWS * CLUSTER_BLOCKS; + this.clusterHeight = this.blockHeight * CLUSTER_BLOCKS; + } + }, { + key: "getNum", + value: function getNum(fixedScroll) { + this.scrollTop = fixedScroll ? this.cache.scrollTop : this.scrollEl.scrollTop; + return Math.floor(this.scrollTop / (this.clusterHeight - this.blockHeight)) || 0; + } + }, { + key: "initData", + value: function initData(rows, num) { + if (rows.length < BLOCK_ROWS) { + return { + topOffset: 0, + bottomOffset: 0, + rowsAbove: 0, + rows: rows + }; + } + + var start = Math.max((this.clusterRows - BLOCK_ROWS) * num, 0); + var end = start + this.clusterRows; + var topOffset = Math.max(start * this.itemHeight, 0); + var bottomOffset = Math.max((rows.length - end) * this.itemHeight, 0); + var thisRows = []; + var rowsAbove = start; + + if (topOffset < 1) { + rowsAbove++; + } + + for (var i = start; i < end; i++) { + rows[i] && thisRows.push(rows[i]); + } + + return { + topOffset: topOffset, + bottomOffset: bottomOffset, + rowsAbove: rowsAbove, + rows: thisRows + }; + } + }, { + key: "checkChanges", + value: function checkChanges(type, value) { + var changed = value !== this.cache[type]; + this.cache[type] = value; + return changed; + } + }, { + key: "getExtra", + value: function getExtra(className, height) { + var tag = document.createElement('tr'); + tag.className = "virtual-scroll-".concat(className); + + if (height) { + tag.style.height = "".concat(height, "px"); + } + + return tag.outerHTML; + } + }]); + + return VirtualScroll; + }(); + + var BootstrapTable = /*#__PURE__*/function () { + function BootstrapTable(el, options) { + _classCallCheck(this, BootstrapTable); + + this.options = options; + this.$el = $__default['default'](el); + this.$el_ = this.$el.clone(); + this.timeoutId_ = 0; + this.timeoutFooter_ = 0; + } + + _createClass(BootstrapTable, [{ + key: "init", + value: function init() { + this.initConstants(); + this.initLocale(); + this.initContainer(); + this.initTable(); + this.initHeader(); + this.initData(); + this.initHiddenRows(); + this.initToolbar(); + this.initPagination(); + this.initBody(); + this.initSearchText(); + this.initServer(); + } + }, { + key: "initConstants", + value: function initConstants() { + var opts = this.options; + this.constants = Constants.CONSTANTS; + this.constants.theme = $__default['default'].fn.bootstrapTable.theme; + this.constants.dataToggle = this.constants.html.dataToggle || 'data-toggle'; + var buttonsPrefix = opts.buttonsPrefix ? "".concat(opts.buttonsPrefix, "-") : ''; + this.constants.buttonsClass = [opts.buttonsPrefix, buttonsPrefix + opts.buttonsClass, Utils.sprintf("".concat(buttonsPrefix, "%s"), opts.iconSize)].join(' ').trim(); + this.buttons = Utils.calculateObjectValue(this, opts.buttons, [], {}); + + if (_typeof(this.buttons) !== 'object') { + this.buttons = {}; + } + + if (typeof opts.icons === 'string') { + opts.icons = Utils.calculateObjectValue(null, opts.icons); + } + } + }, { + key: "initLocale", + value: function initLocale() { + if (this.options.locale) { + var locales = $__default['default'].fn.bootstrapTable.locales; + var parts = this.options.locale.split(/-|_/); + parts[0] = parts[0].toLowerCase(); + + if (parts[1]) { + parts[1] = parts[1].toUpperCase(); + } + + if (locales[this.options.locale]) { + $__default['default'].extend(this.options, locales[this.options.locale]); + } else if (locales[parts.join('-')]) { + $__default['default'].extend(this.options, locales[parts.join('-')]); + } else if (locales[parts[0]]) { + $__default['default'].extend(this.options, locales[parts[0]]); + } + } + } + }, { + key: "initContainer", + value: function initContainer() { + var topPagination = ['top', 'both'].includes(this.options.paginationVAlign) ? '
    ' : ''; + var bottomPagination = ['bottom', 'both'].includes(this.options.paginationVAlign) ? '
    ' : ''; + var loadingTemplate = Utils.calculateObjectValue(this.options, this.options.loadingTemplate, [this.options.formatLoadingMessage()]); + this.$container = $__default['default']("\n
    \n
    \n ").concat(topPagination, "\n
    \n
    \n
    \n
    \n ").concat(loadingTemplate, "\n
    \n
    \n
    \n
    \n ").concat(bottomPagination, "\n
    \n ")); + this.$container.insertAfter(this.$el); + this.$tableContainer = this.$container.find('.fixed-table-container'); + this.$tableHeader = this.$container.find('.fixed-table-header'); + this.$tableBody = this.$container.find('.fixed-table-body'); + this.$tableLoading = this.$container.find('.fixed-table-loading'); + this.$tableFooter = this.$el.find('tfoot'); // checking if custom table-toolbar exists or not + + if (this.options.buttonsToolbar) { + this.$toolbar = $__default['default']('body').find(this.options.buttonsToolbar); + } else { + this.$toolbar = this.$container.find('.fixed-table-toolbar'); + } + + this.$pagination = this.$container.find('.fixed-table-pagination'); + this.$tableBody.append(this.$el); + this.$container.after('
    '); + this.$el.addClass(this.options.classes); + this.$tableLoading.addClass(this.options.classes); + + if (this.options.height) { + this.$tableContainer.addClass('fixed-height'); + + if (this.options.showFooter) { + this.$tableContainer.addClass('has-footer'); + } + + if (this.options.classes.split(' ').includes('table-bordered')) { + this.$tableBody.append('
    '); + this.$tableBorder = this.$tableBody.find('.fixed-table-border'); + this.$tableLoading.addClass('fixed-table-border'); + } - this.$container.insertAfter(this.$el); - this.$tableContainer = this.$container.find('.fixed-table-container'); - this.$tableHeader = this.$container.find('.fixed-table-header'); - this.$tableBody = this.$container.find('.fixed-table-body'); - this.$tableLoading = this.$container.find('.fixed-table-loading'); this.$tableFooter = this.$container.find('.fixed-table-footer'); - // checking if custom table-toolbar exists or not - if (this.options.buttonsToolbar) { - this.$toolbar = $('body').find(this.options.buttonsToolbar); - } else { - this.$toolbar = this.$container.find('.fixed-table-toolbar'); - } - this.$pagination = this.$container.find('.fixed-table-pagination'); - - this.$tableBody.append(this.$el); - this.$container.after('
    '); - - this.$el.addClass(this.options.classes); - this.$tableLoading.addClass(this.options.classes); - - if (this.options.height) { - this.$tableContainer.addClass('fixed-height'); - - if (this.options.showFooter) { - this.$tableContainer.addClass('has-footer'); - } - - if (this.options.classes.split(' ').indexOf('table-bordered') !== -1) { - this.$tableBody.append('
    '); - this.$tableBorder = this.$tableBody.find('.fixed-table-border'); - this.$tableLoading.addClass('fixed-table-border'); - } - } } - }, { - key: 'initTable', - value: function initTable() { - var _this = this; + } + }, { + key: "initTable", + value: function initTable() { + var _this = this; - var columns = []; - var data = []; + var columns = []; + this.$header = this.$el.find('>thead'); - this.$header = this.$el.find('>thead'); - if (!this.$header.length) { - this.$header = $('').appendTo(this.$el); - } else if (this.options.theadClasses) { - this.$header.addClass(this.options.theadClasses); - } - this.$header.find('tr').each(function (i, el) { - var column = []; + if (!this.$header.length) { + this.$header = $__default['default']("")).appendTo(this.$el); + } else if (this.options.theadClasses) { + this.$header.addClass(this.options.theadClasses); + } - $(el).find('th').each(function (i, el) { - // #2014: getFieldIndex and elsewhere assume this is string, causes issues if not - if (typeof $(el).data('field') !== 'undefined') { - $(el).data('field', '' + $(el).data('field')); - } - column.push($.extend({}, { - title: $(el).html(), - 'class': $(el).attr('class'), - titleTooltip: $(el).attr('title'), - rowspan: $(el).attr('rowspan') ? +$(el).attr('rowspan') : undefined, - colspan: $(el).attr('colspan') ? +$(el).attr('colspan') : undefined - }, $(el).data())); - }); - columns.push(column); + this._headerTrClasses = []; + this._headerTrStyles = []; + this.$header.find('tr').each(function (i, el) { + var $tr = $__default['default'](el); + var column = []; + $tr.find('th').each(function (i, el) { + var $th = $__default['default'](el); // #2014: getFieldIndex and elsewhere assume this is string, causes issues if not + + if (typeof $th.data('field') !== 'undefined') { + $th.data('field', "".concat($th.data('field'))); + } + + column.push($__default['default'].extend({}, { + title: $th.html(), + class: $th.attr('class'), + titleTooltip: $th.attr('title'), + rowspan: $th.attr('rowspan') ? +$th.attr('rowspan') : undefined, + colspan: $th.attr('colspan') ? +$th.attr('colspan') : undefined + }, $th.data())); }); + columns.push(column); - if (!Array.isArray(this.options.columns[0])) { - this.options.columns = [this.options.columns]; + if ($tr.attr('class')) { + _this._headerTrClasses.push($tr.attr('class')); } - this.options.columns = $.extend(true, [], columns, this.options.columns); - this.columns = []; - this.fieldsColumnsIndex = []; - - Utils.setFieldIndex(this.options.columns); - - this.options.columns.forEach(function (columns, i) { - columns.forEach(function (_column, j) { - var column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, _column); - - if (typeof column.fieldIndex !== 'undefined') { - _this.columns[column.fieldIndex] = column; - _this.fieldsColumnsIndex[column.field] = column.fieldIndex; - } - - _this.options.columns[i][j] = column; - }); - }); - - // if options.data is setting, do not process tbody data - if (this.options.data.length) { - return; + if ($tr.attr('style')) { + _this._headerTrStyles.push($tr.attr('style')); } + }); - var m = []; - this.$el.find('>tbody>tr').each(function (y, el) { - var row = {}; + if (!Array.isArray(this.options.columns[0])) { + this.options.columns = [this.options.columns]; + } - // save tr's id, class and data-* attributes - row._id = $(el).attr('id'); - row._class = $(el).attr('class'); - row._data = Utils.getRealDataAttr($(el).data()); + this.options.columns = $__default['default'].extend(true, [], columns, this.options.columns); + this.columns = []; + this.fieldsColumnsIndex = []; + Utils.setFieldIndex(this.options.columns); + this.options.columns.forEach(function (columns, i) { + columns.forEach(function (_column, j) { + var column = $__default['default'].extend({}, BootstrapTable.COLUMN_DEFAULTS, _column); - $(el).find('>td').each(function (_x, el) { - var cspan = +$(el).attr('colspan') || 1; - var rspan = +$(el).attr('rowspan') || 1; - var x = _x; + if (typeof column.fieldIndex !== 'undefined') { + _this.columns[column.fieldIndex] = column; + _this.fieldsColumnsIndex[column.field] = column.fieldIndex; + } - // skip already occupied cells in current row - for (; m[y] && m[y][x]; x++) {} - // ignore - - - // mark matrix elements occupied by current cell with true - for (var tx = x; tx < x + cspan; tx++) { - for (var ty = y; ty < y + rspan; ty++) { - if (!m[ty]) { - // fill missing rows - m[ty] = []; - } - m[ty][tx] = true; - } - } - - var field = _this.columns[x].field; - - row[field] = $(el).html().trim(); - // save td's id, class and data-* attributes - row['_' + field + '_id'] = $(el).attr('id'); - row['_' + field + '_class'] = $(el).attr('class'); - row['_' + field + '_rowspan'] = $(el).attr('rowspan'); - row['_' + field + '_colspan'] = $(el).attr('colspan'); - row['_' + field + '_title'] = $(el).attr('title'); - row['_' + field + '_data'] = Utils.getRealDataAttr($(el).data()); - }); - data.push(row); + _this.options.columns[i][j] = column; }); - this.options.data = data; - if (data.length) { + }); // if options.data is setting, do not process tbody and tfoot data + + if (!this.options.data.length) { + var htmlData = Utils.trToData(this.columns, this.$el.find('>tbody>tr')); + + if (htmlData.length) { + this.options.data = htmlData; this.fromHtml = true; } } - }, { - key: 'initHeader', - value: function initHeader() { - var _this2 = this; - var visibleColumns = {}; + if (!(this.options.pagination && this.options.sidePagination !== 'server')) { + this.footerData = Utils.trToData(this.columns, this.$el.find('>tfoot>tr')); + } + + if (this.footerData) { + this.$el.find('tfoot').html(''); + } + + if (!this.options.showFooter || this.options.cardView) { + this.$tableFooter.hide(); + } else { + this.$tableFooter.show(); + } + } + }, { + key: "initHeader", + value: function initHeader() { + var _this2 = this; + + var visibleColumns = {}; + var headerHtml = []; + this.header = { + fields: [], + styles: [], + classes: [], + formatters: [], + detailFormatters: [], + events: [], + sorters: [], + sortNames: [], + cellStyles: [], + searchables: [] + }; + Utils.updateFieldGroup(this.options.columns); + this.options.columns.forEach(function (columns, i) { var html = []; + html.push("")); + var detailViewTemplate = ''; - this.header = { - fields: [], - styles: [], - classes: [], - formatters: [], - events: [], - sorters: [], - sortNames: [], - cellStyles: [], - searchables: [] - }; - - this.options.columns.forEach(function (columns, i) { - html.push(''); - - if (i === 0 && !_this2.options.cardView && _this2.options.detailView) { - html.push('\n
    \n \n '); - } - - columns.forEach(function (column, j) { - var text = ''; - - var halign = ''; // header align style - - var align = ''; // body align style - - var style = ''; - var class_ = Utils.sprintf(' class="%s"', column['class']); - var unitWidth = 'px'; - var width = column.width; - - if (column.width !== undefined && !_this2.options.cardView) { - if (typeof column.width === 'string') { - if (column.width.indexOf('%') !== -1) { - unitWidth = '%'; - } - } - } - if (column.width && typeof column.width === 'string') { - width = column.width.replace('%', '').replace('px', ''); - } - - halign = Utils.sprintf('text-align: %s; ', column.halign ? column.halign : column.align); - align = Utils.sprintf('text-align: %s; ', column.align); - style = Utils.sprintf('vertical-align: %s; ', column.valign); - style += Utils.sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? !column.showSelectTitle ? '36px' : undefined : width ? width + unitWidth : undefined); - - if (typeof column.fieldIndex !== 'undefined') { - _this2.header.fields[column.fieldIndex] = column.field; - _this2.header.styles[column.fieldIndex] = align + style; - _this2.header.classes[column.fieldIndex] = class_; - _this2.header.formatters[column.fieldIndex] = column.formatter; - _this2.header.events[column.fieldIndex] = column.events; - _this2.header.sorters[column.fieldIndex] = column.sorter; - _this2.header.sortNames[column.fieldIndex] = column.sortName; - _this2.header.cellStyles[column.fieldIndex] = column.cellStyle; - _this2.header.searchables[column.fieldIndex] = column.searchable; - - if (!column.visible) { - return; - } - - if (_this2.options.cardView && !column.cardVisible) { - return; - } - - visibleColumns[column.field] = column; - } - - html.push(' 0 ? ' data-not-first-th' : '', '>'); - - html.push(Utils.sprintf('
    ', _this2.options.sortable && column.sortable ? 'sortable both' : '')); - - text = _this2.options.escape ? Utils.escapeHTML(column.title) : column.title; - - var title = text; - if (column.checkbox) { - text = ''; - if (!_this2.options.singleSelect && _this2.options.checkboxHeader) { - text = ''; - } - _this2.header.stateField = column.field; - } - if (column.radio) { - text = ''; - _this2.header.stateField = column.field; - _this2.options.singleSelect = true; - } - if (!text && column.showSelectTitle) { - text += title; - } - - html.push(text); - html.push('
    '); - html.push('
    '); - html.push('
    '); - html.push(''); - }); - html.push(''); - }); - - this.$header.html(html.join('')); - this.$header.find('th[data-field]').each(function (i, el) { - $(el).data(visibleColumns[$(el).data('field')]); - }); - this.$container.off('click', '.th-inner').on('click', '.th-inner', function (e) { - var $this = $(e.currentTarget); - - if (_this2.options.detailView && !$this.parent().hasClass('bs-checkbox')) { - if ($this.closest('.bootstrap-table')[0] !== _this2.$container[0]) { - return false; - } - } - - if (_this2.options.sortable && $this.parent().data().sortable) { - _this2.onSort(e); - } - }); - - this.$header.children().children().off('keypress').on('keypress', function (e) { - if (_this2.options.sortable && $(e.currentTarget).data().sortable) { - var code = e.keyCode || e.which; - if (code === 13) { - // Enter keycode - _this2.onSort(e); - } - } - }); - - $(window).off('resize.bootstrap-table'); - if (!this.options.showHeader || this.options.cardView) { - this.$header.hide(); - this.$tableHeader.hide(); - this.$tableLoading.css('top', 0); - } else { - this.$header.show(); - this.$tableHeader.show(); - this.$tableLoading.css('top', this.$header.outerHeight() + 1); - // Assign the correct sortable arrow - this.getCaret(); - $(window).on('resize.bootstrap-table', function (e) { - return _this2.resetWidth(e); - }); + if (i === 0 && Utils.hasDetailViewIcon(_this2.options)) { + var rowspan = _this2.options.columns.length > 1 ? " rowspan=\"".concat(_this2.options.columns.length, "\"") : ''; + detailViewTemplate = "\n
    \n "); } - this.$selectAll = this.$header.find('[name="btSelectAll"]'); - this.$selectAll.off('click').on('click', function (_ref12) { - var currentTarget = _ref12.currentTarget; - - var checked = $(currentTarget).prop('checked'); - _this2[checked ? 'checkAll' : 'uncheckAll'](); - _this2.updateSelected(); - }); - } - }, { - key: 'initFooter', - value: function initFooter() { - if (!this.options.showFooter || this.options.cardView) { - this.$tableFooter.hide(); - } else { - this.$tableFooter.show(); - } - } - }, { - key: 'initData', - value: function initData(data, type) { - if (type === 'append') { - this.options.data = this.options.data.concat(data); - } else if (type === 'prepend') { - this.options.data = [].concat(data).concat(this.options.data); - } else { - this.options.data = data || this.options.data; + if (detailViewTemplate && _this2.options.detailViewAlign !== 'right') { + html.push(detailViewTemplate); } - this.data = this.options.data; + columns.forEach(function (column, j) { + var class_ = Utils.sprintf(' class="%s"', column['class']); + var unitWidth = column.widthUnit; + var width = parseFloat(column.width); + var halign = Utils.sprintf('text-align: %s; ', column.halign ? column.halign : column.align); + var align = Utils.sprintf('text-align: %s; ', column.align); + var style = Utils.sprintf('vertical-align: %s; ', column.valign); + style += Utils.sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? !column.showSelectTitle ? '36px' : undefined : width ? width + unitWidth : undefined); - if (this.options.sidePagination === 'server') { - return; - } - this.initSort(); - } - }, { - key: 'initSort', - value: function initSort() { - var _this3 = this; - - var name = this.options.sortName; - var order = this.options.sortOrder === 'desc' ? -1 : 1; - var index = this.header.fields.indexOf(this.options.sortName); - var timeoutId = 0; - - if (index !== -1) { - if (this.options.sortStable) { - this.data.forEach(function (row, i) { - if (!row.hasOwnProperty('_position')) { - row._position = i; - } - }); - } - - if (this.options.customSort) { - Utils.calculateObjectValue(this.options, this.options.customSort, [this.options.sortName, this.options.sortOrder, this.data]); - } else { - this.data.sort(function (a, b) { - if (_this3.header.sortNames[index]) { - name = _this3.header.sortNames[index]; - } - var aa = Utils.getItemField(a, name, _this3.options.escape); - var bb = Utils.getItemField(b, name, _this3.options.escape); - var value = Utils.calculateObjectValue(_this3.header, _this3.header.sorters[index], [aa, bb, a, b]); - - if (value !== undefined) { - if (_this3.options.sortStable && value === 0) { - return order * (a._position - b._position); - } - return order * value; - } - - // Fix #161: undefined or null string sort bug. - if (aa === undefined || aa === null) { - aa = ''; - } - if (bb === undefined || bb === null) { - bb = ''; - } - - if (_this3.options.sortStable && aa === bb) { - aa = a._position; - bb = b._position; - } - - // IF both values are numeric, do a numeric comparison - if (Utils.isNumeric(aa) && Utils.isNumeric(bb)) { - // Convert numerical values form string to float. - aa = parseFloat(aa); - bb = parseFloat(bb); - if (aa < bb) { - return order * -1; - } - if (aa > bb) { - return order; - } - return 0; - } - - if (aa === bb) { - return 0; - } - - // If value is not a string, convert to string - if (typeof aa !== 'string') { - aa = aa.toString(); - } - - if (aa.localeCompare(bb) === -1) { - return order * -1; - } - - return order; - }); - } - - if (this.options.sortClass !== undefined) { - clearTimeout(timeoutId); - timeoutId = setTimeout(function () { - _this3.$el.removeClass(_this3.options.sortClass); - var index = _this3.$header.find('[data-field="' + _this3.options.sortName + '"]').index(); - _this3.$el.find('tr td:nth-child(' + (index + 1) + ')').addClass(_this3.options.sortClass); - }, 250); - } - } - } - }, { - key: 'onSort', - value: function onSort(_ref13) { - var type = _ref13.type, - currentTarget = _ref13.currentTarget; - - var $this = type === 'keypress' ? $(currentTarget) : $(currentTarget).parent(); - var $this_ = this.$header.find('th').eq($this.index()); - - this.$header.add(this.$header_).find('span.order').remove(); - - if (this.options.sortName === $this.data('field')) { - this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc'; - } else { - this.options.sortName = $this.data('field'); - if (this.options.rememberOrder) { - this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc'; - } else { - this.options.sortOrder = this.columns[this.fieldsColumnsIndex[$this.data('field')]].order; - } - } - this.trigger('sort', this.options.sortName, this.options.sortOrder); - - $this.add($this_).data('order', this.options.sortOrder); - - // Assign the correct sortable arrow - this.getCaret(); - - if (this.options.sidePagination === 'server') { - this.initServer(this.options.silentSort); - return; - } - - this.initSort(); - this.initBody(); - } - }, { - key: 'initToolbar', - value: function initToolbar() { - var _this4 = this; - - var o = this.options; - var html = []; - var timeoutId = 0; - var $keepOpen = void 0; - var $search = void 0; - var switchableCount = 0; - - if (this.$toolbar.find('.bs-bars').children().length) { - $('body').append($(o.toolbar)); - } - this.$toolbar.html(''); - - if (typeof o.toolbar === 'string' || _typeof(o.toolbar) === 'object') { - $(Utils.sprintf('
    ', this.constants.classes.pull, o.toolbarAlign)).appendTo(this.$toolbar).append($(o.toolbar)); - } - - // showColumns, showToggle, showRefresh - html = ['
    ']; - - if (typeof o.icons === 'string') { - o.icons = Utils.calculateObjectValue(null, o.icons); - } - - if (o.showPaginationSwitch) { - html.push(''); - } - - if (o.showRefresh) { - html.push(''); - } - - if (o.showToggle) { - html.push(''); - } - - if (o.showFullscreen) { - html.push(''); - } - - if (o.showColumns) { - html.push('
    \n \n ' + this.constants.html.toobarDropdow[0]); - - this.columns.forEach(function (column, i) { - if (column.radio || column.checkbox) { - return; - } - - if (o.cardView && !column.cardVisible) { - return; - } - - var checked = column.visible ? ' checked="checked"' : ''; - - if (column.switchable) { - html.push(Utils.sprintf(_this4.constants.html.toobarDropdowItem, Utils.sprintf(' %s', column.field, i, checked, column.title))); - switchableCount++; - } - }); - html.push(this.constants.html.toobarDropdow[1], '
    '); - } - - html.push('
    '); - - // Fix #188: this.showToolbar is for extensions - if (this.showToolbar || html.length > 2) { - this.$toolbar.append(html.join('')); - } - - if (o.showPaginationSwitch) { - this.$toolbar.find('button[name="paginationSwitch"]').off('click').on('click', function () { - return _this4.togglePagination(); - }); - } - - if (o.showFullscreen) { - this.$toolbar.find('button[name="fullscreen"]').off('click').on('click', function () { - return _this4.toggleFullscreen(); - }); - } - - if (o.showRefresh) { - this.$toolbar.find('button[name="refresh"]').off('click').on('click', function () { - return _this4.refresh(); - }); - } - - if (o.showToggle) { - this.$toolbar.find('button[name="toggle"]').off('click').on('click', function () { - _this4.toggleView(); - }); - } - - if (o.showColumns) { - $keepOpen = this.$toolbar.find('.keep-open'); - - if (switchableCount <= o.minimumCountColumns) { - $keepOpen.find('input').prop('disabled', true); - } - - $keepOpen.find('li, label').off('click').on('click', function (e) { - e.stopImmediatePropagation(); - }); - $keepOpen.find('input').off('click').on('click', function (_ref14) { - var currentTarget = _ref14.currentTarget; - - var $this = $(currentTarget); - - _this4.toggleColumn($this.val(), $this.prop('checked'), false); - _this4.trigger('column-switch', $this.data('field'), $this.prop('checked')); - }); - } - - if (o.search) { - html = []; - html.push(''); - - this.$toolbar.append(html.join('')); - $search = this.$toolbar.find('.search input'); - $search.off('keyup drop blur').on('keyup drop blur', function (event) { - if (o.searchOnEnterKey && event.keyCode !== 13) { - return; - } - - if ([37, 38, 39, 40].indexOf(event.keyCode) !== -1) { - return; - } - - clearTimeout(timeoutId); // doesn't matter if it's 0 - timeoutId = setTimeout(function () { - _this4.onSearch(event); - }, o.searchTimeOut); - }); - - if (Utils.isIEBrowser()) { - $search.off('mouseup').on('mouseup', function (event) { - clearTimeout(timeoutId); // doesn't matter if it's 0 - timeoutId = setTimeout(function () { - _this4.onSearch(event); - }, o.searchTimeOut); - }); - } - } - } - }, { - key: 'onSearch', - value: function onSearch(_ref15) { - var currentTarget = _ref15.currentTarget, - firedByInitSearchText = _ref15.firedByInitSearchText; - - var text = $(currentTarget).val().trim(); - - // trim search input - if (this.options.trimOnSearch && $(currentTarget).val() !== text) { - $(currentTarget).val(text); - } - - if (text === this.searchText) { - return; - } - this.searchText = text; - this.options.searchText = text; - - if (!firedByInitSearchText) { - this.options.pageNumber = 1; - } - this.initSearch(); - if (firedByInitSearchText) { - if (this.options.sidePagination === 'client') { - this.updatePagination(); - } - } else { - this.updatePagination(); - } - this.trigger('search', text); - } - }, { - key: 'initSearch', - value: function initSearch() { - var _this5 = this; - - if (this.options.sidePagination !== 'server') { - if (this.options.customSearch) { - this.data = Utils.calculateObjectValue(this.options, this.options.customSearch, [this.options.data, this.searchText]); + if (typeof column.fieldIndex === 'undefined' && !column.visible) { return; } - var s = this.searchText && (this.options.escape ? Utils.escapeHTML(this.searchText) : this.searchText).toLowerCase(); - var f = Utils.isEmptyObject(this.filterColumns) ? null : this.filterColumns; + var headerStyle = Utils.calculateObjectValue(null, _this2.options.headerStyle, [column]); + var csses = []; + var classes = ''; - // Check filter - this.data = f ? this.options.data.filter(function (item, i) { - for (var key in f) { - if (Array.isArray(f[key]) && !(f[key].indexOf(item[key]) !== -1) || !Array.isArray(f[key]) && item[key] !== f[key]) { - return false; - } - } - return true; - }) : this.options.data; + if (headerStyle && headerStyle.css) { + for (var _i = 0, _Object$entries = Object.entries(headerStyle.css); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), + key = _Object$entries$_i[0], + value = _Object$entries$_i[1]; - this.data = s ? this.data.filter(function (item, i) { - for (var j = 0; j < _this5.header.fields.length; j++) { - if (!_this5.header.searchables[j]) { - continue; - } - - var key = Utils.isNumeric(_this5.header.fields[j]) ? parseInt(_this5.header.fields[j], 10) : _this5.header.fields[j]; - var column = _this5.columns[_this5.fieldsColumnsIndex[key]]; - var value = void 0; - - if (typeof key === 'string') { - value = item; - var props = key.split('.'); - for (var _i10 = 0; _i10 < props.length; _i10++) { - if (value[props[_i10]] !== null) { - value = value[props[_i10]]; - } - } - } else { - value = item[key]; - } - - // Fix #142: respect searchForamtter boolean - if (column && column.searchFormatter) { - value = Utils.calculateObjectValue(column, _this5.header.formatters[j], [value, item, i], value); - } - - if (typeof value === 'string' || typeof value === 'number') { - if (_this5.options.strictSearch) { - if (('' + value).toLowerCase() === s) { - return true; - } - } else { - if (('' + value).toLowerCase().indexOf(s) !== -1) { - return true; - } - } - } - } - return false; - }) : this.data; - } - } - }, { - key: 'initPagination', - value: function initPagination() { - var _this6 = this; - - var o = this.options; - if (!o.pagination) { - this.$pagination.hide(); - return; - } - this.$pagination.show(); - - var html = []; - var $allSelected = false; - var i = void 0; - var from = void 0; - var to = void 0; - var $pageList = void 0; - var $pre = void 0; - var $next = void 0; - var $number = void 0; - var data = this.getData(); - var pageList = o.pageList; - - if (o.sidePagination !== 'server') { - o.totalRows = data.length; - } - - this.totalPages = 0; - if (o.totalRows) { - if (o.pageSize === o.formatAllRows()) { - o.pageSize = o.totalRows; - $allSelected = true; - } else if (o.pageSize === o.totalRows) { - // Fix #667 Table with pagination, - // multiple pages and a search this matches to one page throws exception - var pageLst = typeof o.pageList === 'string' ? o.pageList.replace('[', '').replace(']', '').replace(/ /g, '').toLowerCase().split(',') : o.pageList; - if (pageLst.indexOf(o.formatAllRows().toLowerCase()) !== -1) { - $allSelected = true; + csses.push("".concat(key, ": ").concat(value)); } } - this.totalPages = ~~((o.totalRows - 1) / o.pageSize) + 1; - - o.totalPages = this.totalPages; - } - if (this.totalPages > 0 && o.pageNumber > this.totalPages) { - o.pageNumber = this.totalPages; - } - - this.pageFrom = (o.pageNumber - 1) * o.pageSize + 1; - this.pageTo = o.pageNumber * o.pageSize; - if (this.pageTo > o.totalRows) { - this.pageTo = o.totalRows; - } - - var paginationInfo = o.onlyInfoPagination ? o.formatDetailPagination(o.totalRows) : o.formatShowingRows(this.pageFrom, this.pageTo, o.totalRows); - - html.push('
    \n \n ' + paginationInfo + '\n '); - - if (!o.onlyInfoPagination) { - html.push(''); - - var pageNumber = ['\n \n ' + this.constants.html.pageDropdown[0]]; - - if (typeof o.pageList === 'string') { - var list = o.pageList.replace('[', '').replace(']', '').replace(/ /g, '').split(','); - - pageList = []; - for (var _iterator9 = list, _isArray9 = Array.isArray(_iterator9), _i11 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { - var _ref16; - - if (_isArray9) { - if (_i11 >= _iterator9.length) break; - _ref16 = _iterator9[_i11++]; - } else { - _i11 = _iterator9.next(); - if (_i11.done) break; - _ref16 = _i11.value; - } - - var value = _ref16; - - pageList.push(value.toUpperCase() === o.formatAllRows().toUpperCase() || value.toUpperCase() === 'UNLIMITED' ? o.formatAllRows() : +value); - } + if (headerStyle && headerStyle.classes) { + classes = Utils.sprintf(' class="%s"', column['class'] ? [column['class'], headerStyle.classes].join(' ') : headerStyle.classes); } - pageList.forEach(function (page, i) { - if (!o.smartDisplay || i === 0 || pageList[i - 1] < o.totalRows) { - var active = void 0; - if ($allSelected) { - active = page === o.formatAllRows() ? _this6.constants.classes.dropdownActive : ''; - } else { - active = page === o.pageSize ? _this6.constants.classes.dropdownActive : ''; - } - pageNumber.push(Utils.sprintf(_this6.constants.html.pageDropdownItem, active, page)); - } - }); - pageNumber.push(this.constants.html.pageDropdown[1] + ''); + if (typeof column.fieldIndex !== 'undefined') { + _this2.header.fields[column.fieldIndex] = column.field; + _this2.header.styles[column.fieldIndex] = align + style; + _this2.header.classes[column.fieldIndex] = class_; + _this2.header.formatters[column.fieldIndex] = column.formatter; + _this2.header.detailFormatters[column.fieldIndex] = column.detailFormatter; + _this2.header.events[column.fieldIndex] = column.events; + _this2.header.sorters[column.fieldIndex] = column.sorter; + _this2.header.sortNames[column.fieldIndex] = column.sortName; + _this2.header.cellStyles[column.fieldIndex] = column.cellStyle; + _this2.header.searchables[column.fieldIndex] = column.searchable; - html.push(o.formatRecordsPerPage(pageNumber.join(''))); - html.push('
    '); - - html.push(''); - } - this.$pagination.html(html.join('')); - - var dropupClass = ['bottom', 'both'].indexOf(o.paginationVAlign) !== -1 ? ' ' + this.constants.classes.dropup : ''; - this.$pagination.last().find('.page-list > span').addClass(dropupClass); - - if (!o.onlyInfoPagination) { - $pageList = this.$pagination.find('.page-list a'); - $pre = this.$pagination.find('.page-pre'); - $next = this.$pagination.find('.page-next'); - $number = this.$pagination.find('.page-item').not('.page-next, .page-pre'); - - if (o.smartDisplay) { - if (this.totalPages <= 1) { - this.$pagination.find('div.pagination').hide(); - } - if (pageList.length < 2 || o.totalRows <= pageList[0]) { - this.$pagination.find('span.page-list').hide(); - } - - // when data is empty, hide the pagination - this.$pagination[this.getData().length ? 'show' : 'hide'](); - } - - if (!o.paginationLoop) { - if (o.pageNumber === 1) { - $pre.addClass('disabled'); - } - if (o.pageNumber === this.totalPages) { - $next.addClass('disabled'); - } - } - - if ($allSelected) { - o.pageSize = o.formatAllRows(); - } - // removed the events for last and first, onPageNumber executeds the same logic - $pageList.off('click').on('click', function (e) { - return _this6.onPageListChange(e); - }); - $pre.off('click').on('click', function (e) { - return _this6.onPagePre(e); - }); - $next.off('click').on('click', function (e) { - return _this6.onPageNext(e); - }); - $number.off('click').on('click', function (e) { - return _this6.onPageNumber(e); - }); - } - } - }, { - key: 'updatePagination', - value: function updatePagination(event) { - // Fix #171: IE disabled button can be clicked bug. - if (event && $(event.currentTarget).hasClass('disabled')) { - return; - } - - if (!this.options.maintainSelected) { - this.resetRows(); - } - - this.initPagination(); - if (this.options.sidePagination === 'server') { - this.initServer(); - } else { - this.initBody(); - } - - this.trigger('page-change', this.options.pageNumber, this.options.pageSize); - } - }, { - key: 'onPageListChange', - value: function onPageListChange(event) { - event.preventDefault(); - var $this = $(event.currentTarget); - - $this.parent().addClass(this.constants.classes.dropdownActive).siblings().removeClass(this.constants.classes.dropdownActive); - this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? this.options.formatAllRows() : +$this.text(); - this.$toolbar.find('.page-size').text(this.options.pageSize); - - this.updatePagination(event); - return false; - } - }, { - key: 'onPagePre', - value: function onPagePre(event) { - event.preventDefault(); - if (this.options.pageNumber - 1 === 0) { - this.options.pageNumber = this.options.totalPages; - } else { - this.options.pageNumber--; - } - this.updatePagination(event); - return false; - } - }, { - key: 'onPageNext', - value: function onPageNext(event) { - event.preventDefault(); - if (this.options.pageNumber + 1 > this.options.totalPages) { - this.options.pageNumber = 1; - } else { - this.options.pageNumber++; - } - this.updatePagination(event); - return false; - } - }, { - key: 'onPageNumber', - value: function onPageNumber(event) { - event.preventDefault(); - if (this.options.pageNumber === +$(event.currentTarget).text()) { - return; - } - this.options.pageNumber = +$(event.currentTarget).text(); - this.updatePagination(event); - return false; - } - }, { - key: 'initRow', - value: function initRow(item, i, data, parentDom) { - var _this7 = this; - - var html = []; - var style = {}; - var csses = []; - var data_ = ''; - var attributes = {}; - var htmlAttributes = []; - - if (Utils.findIndex(this.hiddenRows, item) > -1) { - return; - } - - style = Utils.calculateObjectValue(this.options, this.options.rowStyle, [item, i], style); - - if (style && style.css) { - for (var _iterator10 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(style.css), _isArray10 = Array.isArray(_iterator10), _i12 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { - var _ref17; - - if (_isArray10) { - if (_i12 >= _iterator10.length) break; - _ref17 = _iterator10[_i12++]; - } else { - _i12 = _iterator10.next(); - if (_i12.done) break; - _ref17 = _i12.value; - } - - var _ref18 = _ref17, - _ref19 = _slicedToArray(_ref18, 2), - key = _ref19[0], - value = _ref19[1]; - - csses.push(key + ': ' + value); - } - } - - attributes = Utils.calculateObjectValue(this.options, this.options.rowAttributes, [item, i], attributes); - - if (attributes) { - for (var _iterator11 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(attributes), _isArray11 = Array.isArray(_iterator11), _i13 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) { - var _ref20; - - if (_isArray11) { - if (_i13 >= _iterator11.length) break; - _ref20 = _iterator11[_i13++]; - } else { - _i13 = _iterator11.next(); - if (_i13.done) break; - _ref20 = _i13.value; - } - - var _ref21 = _ref20, - _ref22 = _slicedToArray(_ref21, 2), - _key2 = _ref22[0], - _value2 = _ref22[1]; - - htmlAttributes.push(_key2 + '="' + Utils.escapeHTML(_value2) + '"'); - } - } - - if (item._data && !Utils.isEmptyObject(item._data)) { - for (var _iterator12 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(item._data), _isArray12 = Array.isArray(_iterator12), _i14 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) { - var _ref23; - - if (_isArray12) { - if (_i14 >= _iterator12.length) break; - _ref23 = _iterator12[_i14++]; - } else { - _i14 = _iterator12.next(); - if (_i14.done) break; - _ref23 = _i14.value; - } - - var _ref24 = _ref23, - _ref25 = _slicedToArray(_ref24, 2), - k = _ref25[0], - v = _ref25[1]; - - // ignore data-index - if (k === 'index') { + if (!column.visible) { return; } - data_ += ' data-' + k + '="' + v + '"'; - } - } - html.push(''); - - if (this.options.cardView) { - html.push('
    '); - } - - if (!this.options.cardView && this.options.detailView) { - html.push(''); - - if (Utils.calculateObjectValue(null, this.options.detailFilter, [i, item])) { - html.push('\n \n ' + Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen) + '\n \n '); - } - - html.push(''); - } - - this.header.fields.forEach(function (field, j) { - var text = ''; - var value_ = Utils.getItemField(item, field, _this7.options.escape); - var value = ''; - var type = ''; - var cellStyle = {}; - var id_ = ''; - var class_ = _this7.header.classes[j]; - var style_ = ''; - var data_ = ''; - var rowspan_ = ''; - var colspan_ = ''; - var title_ = ''; - var column = _this7.columns[j]; - - if (_this7.fromHtml && typeof value_ === 'undefined') { - if (!column.checkbox && !column.radio) { + if (_this2.options.cardView && !column.cardVisible) { return; } + + visibleColumns[column.field] = column; } - if (!column.visible) { - return; - } + html.push(" 0 ? ' data-not-first-th' : '', '>'); + html.push(Utils.sprintf('
    ', _this2.options.sortable && column.sortable ? 'sortable both' : '')); + var text = _this2.options.escape ? Utils.escapeHTML(column.title) : column.title; + var title = text; - if (_this7.options.cardView && !column.cardVisible) { - return; - } + if (column.checkbox) { + text = ''; - if (column.escape) { - value_ = Utils.escapeHTML(value_); - } - - if (csses.concat([_this7.header.styles[j]]).length) { - style_ = ' style="' + csses.concat([_this7.header.styles[j]]).join('; ') + '"'; - } - // handle td's id and class - if (item['_' + field + '_id']) { - id_ = Utils.sprintf(' id="%s"', item['_' + field + '_id']); - } - if (item['_' + field + '_class']) { - class_ = Utils.sprintf(' class="%s"', item['_' + field + '_class']); - } - if (item['_' + field + '_rowspan']) { - rowspan_ = Utils.sprintf(' rowspan="%s"', item['_' + field + '_rowspan']); - } - if (item['_' + field + '_colspan']) { - colspan_ = Utils.sprintf(' colspan="%s"', item['_' + field + '_colspan']); - } - if (item['_' + field + '_title']) { - title_ = Utils.sprintf(' title="%s"', item['_' + field + '_title']); - } - cellStyle = Utils.calculateObjectValue(_this7.header, _this7.header.cellStyles[j], [value_, item, i, field], cellStyle); - if (cellStyle.classes) { - class_ = ' class="' + cellStyle.classes + '"'; - } - if (cellStyle.css) { - var csses_ = []; - for (var _iterator13 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(cellStyle.css), _isArray13 = Array.isArray(_iterator13), _i15 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) { - var _ref26; - - if (_isArray13) { - if (_i15 >= _iterator13.length) break; - _ref26 = _iterator13[_i15++]; - } else { - _i15 = _iterator13.next(); - if (_i15.done) break; - _ref26 = _i15.value; - } - - var _ref27 = _ref26, - _ref28 = _slicedToArray(_ref27, 2), - _key3 = _ref28[0], - _value3 = _ref28[1]; - - csses_.push(_key3 + ': ' + _value3); + if (!_this2.options.singleSelect && _this2.options.checkboxHeader) { + text = ''; } - style_ = ' style="' + csses_.concat(_this7.header.styles[j]).join('; ') + '"'; + + _this2.header.stateField = column.field; } - value = Utils.calculateObjectValue(column, _this7.header.formatters[j], [value_, item, i, field], value_); - - if (item['_' + field + '_data'] && !Utils.isEmptyObject(item['_' + field + '_data'])) { - for (var _iterator14 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(item['_' + field + '_data']), _isArray14 = Array.isArray(_iterator14), _i16 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) { - var _ref29; - - if (_isArray14) { - if (_i16 >= _iterator14.length) break; - _ref29 = _iterator14[_i16++]; - } else { - _i16 = _iterator14.next(); - if (_i16.done) break; - _ref29 = _i16.value; - } - - var _ref30 = _ref29, - _ref31 = _slicedToArray(_ref30, 2), - _k2 = _ref31[0], - _v = _ref31[1]; - - // ignore data-index - if (_k2 === 'index') { - return; - } - data_ += ' data-' + _k2 + '="' + _v + '"'; - } + if (column.radio) { + text = ''; + _this2.header.stateField = column.field; } - if (column.checkbox || column.radio) { - type = column.checkbox ? 'checkbox' : type; - type = column.radio ? 'radio' : type; - - var c = column['class'] || ''; - var isChecked = value === true || value_ || value && value.checked; - var isDisabled = !column.checkboxEnabled || value && value.disabled; - - text = [_this7.options.cardView ? '
    ' : '', '', _this7.header.formatters[j] && typeof value === 'string' ? value : '', _this7.options.cardView ? '
    ' : ''].join(''); - - item[_this7.header.stateField] = value === true || !!value_ || value && value.checked; - } else { - value = typeof value === 'undefined' || value === null ? _this7.options.undefinedText : value; - - if (_this7.options.cardView) { - var cardTitle = _this7.options.showHeader ? '' + Utils.getFieldTitle(_this7.columns, field) + '' : ''; - - text = '
    ' + cardTitle + '' + value + '
    '; - - if (_this7.options.smartDisplay && value === '') { - text = '
    '; - } - } else { - text = '' + value + ''; - } + if (!text && column.showSelectTitle) { + text += title; } html.push(text); + html.push('
    '); + html.push('
    '); + html.push('
    '); + html.push(''); }); - if (this.options.cardView) { - html.push('
    '); + if (detailViewTemplate && _this2.options.detailViewAlign === 'right') { + html.push(detailViewTemplate); } + html.push(''); - return html.join(''); + if (html.length > 3) { + headerHtml.push(html.join('')); + } + }); + this.$header.html(headerHtml.join('')); + this.$header.find('th[data-field]').each(function (i, el) { + $__default['default'](el).data(visibleColumns[$__default['default'](el).data('field')]); + }); + this.$container.off('click', '.th-inner').on('click', '.th-inner', function (e) { + var $this = $__default['default'](e.currentTarget); + + if (_this2.options.detailView && !$this.parent().hasClass('bs-checkbox')) { + if ($this.closest('.bootstrap-table')[0] !== _this2.$container[0]) { + return false; + } + } + + if (_this2.options.sortable && $this.parent().data().sortable) { + _this2.onSort(e); + } + }); + this.$header.children().children().off('keypress').on('keypress', function (e) { + if (_this2.options.sortable && $__default['default'](e.currentTarget).data().sortable) { + var code = e.keyCode || e.which; + + if (code === 13) { + // Enter keycode + _this2.onSort(e); + } + } + }); + var resizeEvent = Utils.getEventName('resize.bootstrap-table', this.$el.attr('id')); + $__default['default'](window).off(resizeEvent); + + if (!this.options.showHeader || this.options.cardView) { + this.$header.hide(); + this.$tableHeader.hide(); + this.$tableLoading.css('top', 0); + } else { + this.$header.show(); + this.$tableHeader.show(); + this.$tableLoading.css('top', this.$header.outerHeight() + 1); // Assign the correct sortable arrow + + this.getCaret(); + $__default['default'](window).on(resizeEvent, function () { + return _this2.resetView(); + }); } - }, { - key: 'initBody', - value: function initBody(fixedScroll) { - var _this8 = this; - var data = this.getData(); + this.$selectAll = this.$header.find('[name="btSelectAll"]'); + this.$selectAll.off('click').on('click', function (e) { + e.stopPropagation(); + var checked = $__default['default'](e.currentTarget).prop('checked'); - this.trigger('pre-body', data); + _this2[checked ? 'checkAll' : 'uncheckAll'](); - this.$body = this.$el.find('>tbody'); - if (!this.$body.length) { - this.$body = $('').appendTo(this.$el); + _this2.updateSelected(); + }); + } + }, { + key: "initData", + value: function initData(data, type) { + if (type === 'append') { + this.options.data = this.options.data.concat(data); + } else if (type === 'prepend') { + this.options.data = [].concat(data).concat(this.options.data); + } else { + data = data || Utils.deepCopy(this.options.data); + this.options.data = Array.isArray(data) ? data : data[this.options.dataField]; + } + + this.data = _toConsumableArray(this.options.data); + + if (this.options.sortReset) { + this.unsortedData = _toConsumableArray(this.data); + } + + if (this.options.sidePagination === 'server') { + return; + } + + this.initSort(); + } + }, { + key: "initSort", + value: function initSort() { + var _this3 = this; + + var name = this.options.sortName; + var order = this.options.sortOrder === 'desc' ? -1 : 1; + var index = this.header.fields.indexOf(this.options.sortName); + var timeoutId = 0; + + if (index !== -1) { + if (this.options.sortStable) { + this.data.forEach(function (row, i) { + if (!row.hasOwnProperty('_position')) { + row._position = i; + } + }); } - // Fix #389 Bootstrap-table-flatJSON is not working - if (!this.options.pagination || this.options.sidePagination === 'server') { - this.pageFrom = 1; - this.pageTo = data.length; - } - - var trFragments = $(document.createDocumentFragment()); - var hasTr = false; - - for (var i = this.pageFrom - 1; i < this.pageTo; i++) { - var item = data[i]; - var tr = this.initRow(item, i, data, trFragments); - hasTr = hasTr || !!tr; - if (tr && typeof tr === 'string') { - trFragments.append(tr); - } - } - - // show no records - if (!hasTr) { - this.$body.html('' + Utils.sprintf('%s', this.$header.find('th').length, this.options.formatNoMatches()) + ''); + if (this.options.customSort) { + Utils.calculateObjectValue(this.options, this.options.customSort, [this.options.sortName, this.options.sortOrder, this.data]); } else { - this.$body.html(trFragments); + this.data.sort(function (a, b) { + if (_this3.header.sortNames[index]) { + name = _this3.header.sortNames[index]; + } + + var aa = Utils.getItemField(a, name, _this3.options.escape); + var bb = Utils.getItemField(b, name, _this3.options.escape); + var value = Utils.calculateObjectValue(_this3.header, _this3.header.sorters[index], [aa, bb, a, b]); + + if (value !== undefined) { + if (_this3.options.sortStable && value === 0) { + return order * (a._position - b._position); + } + + return order * value; + } + + return Utils.sort(aa, bb, order, _this3.options.sortStable, a._position, b._position); + }); } - if (!fixedScroll) { - this.scrollTo(0); + if (this.options.sortClass !== undefined) { + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + _this3.$el.removeClass(_this3.options.sortClass); + + var index = _this3.$header.find("[data-field=\"".concat(_this3.options.sortName, "\"]")).index(); + + _this3.$el.find("tr td:nth-child(".concat(index + 1, ")")).addClass(_this3.options.sortClass); + }, 250); + } + } else if (this.options.sortReset) { + this.data = _toConsumableArray(this.unsortedData); + } + } + }, { + key: "onSort", + value: function onSort(_ref) { + var type = _ref.type, + currentTarget = _ref.currentTarget; + var $this = type === 'keypress' ? $__default['default'](currentTarget) : $__default['default'](currentTarget).parent(); + var $this_ = this.$header.find('th').eq($this.index()); + this.$header.add(this.$header_).find('span.order').remove(); + + if (this.options.sortName === $this.data('field')) { + var currentSortOrder = this.options.sortOrder; + + if (currentSortOrder === undefined) { + this.options.sortOrder = 'asc'; + } else if (currentSortOrder === 'asc') { + this.options.sortOrder = 'desc'; + } else if (this.options.sortOrder === 'desc') { + this.options.sortOrder = this.options.sortReset ? undefined : 'asc'; } - // click to select by column - this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (_ref32) { - var currentTarget = _ref32.currentTarget, - type = _ref32.type, - target = _ref32.target; + if (this.options.sortOrder === undefined) { + this.options.sortName = undefined; + } + } else { + this.options.sortName = $this.data('field'); - var $td = $(currentTarget); - var $tr = $td.parent(); - var $cardviewArr = $(target).parents('.card-views').children(); - var $cardviewTarget = $(target).parents('.card-view'); - var item = _this8.data[$tr.data('index')]; - var index = _this8.options.cardView ? $cardviewArr.index($cardviewTarget) : $td[0].cellIndex; - var fields = _this8.getVisibleFields(); - var field = fields[_this8.options.detailView && !_this8.options.cardView ? index - 1 : index]; - var column = _this8.columns[_this8.fieldsColumnsIndex[field]]; - var value = Utils.getItemField(item, field, _this8.options.escape); + if (this.options.rememberOrder) { + this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc'; + } else { + this.options.sortOrder = this.columns[this.fieldsColumnsIndex[$this.data('field')]].sortOrder || this.columns[this.fieldsColumnsIndex[$this.data('field')]].order; + } + } - if ($td.find('.detail-icon').length) { - return; + this.trigger('sort', this.options.sortName, this.options.sortOrder); + $this.add($this_).data('order', this.options.sortOrder); // Assign the correct sortable arrow + + this.getCaret(); + + if (this.options.sidePagination === 'server' && this.options.serverSort) { + this.options.pageNumber = 1; + this.initServer(this.options.silentSort); + return; + } + + this.initSort(); + this.initBody(); + } + }, { + key: "initToolbar", + value: function initToolbar() { + var _this4 = this; + + var opts = this.options; + var html = []; + var timeoutId = 0; + var $keepOpen; + var switchableCount = 0; + + if (this.$toolbar.find('.bs-bars').children().length) { + $__default['default']('body').append($__default['default'](opts.toolbar)); + } + + this.$toolbar.html(''); + + if (typeof opts.toolbar === 'string' || _typeof(opts.toolbar) === 'object') { + $__default['default'](Utils.sprintf('
    ', this.constants.classes.pull, opts.toolbarAlign)).appendTo(this.$toolbar).append($__default['default'](opts.toolbar)); + } // showColumns, showToggle, showRefresh + + + html = ["
    ")]; + + if (typeof opts.buttonsOrder === 'string') { + opts.buttonsOrder = opts.buttonsOrder.replace(/\[|\]| |'/g, '').split(','); + } + + this.buttons = Object.assign(this.buttons, { + paginationSwitch: { + text: opts.pagination ? opts.formatPaginationSwitchUp() : opts.formatPaginationSwitchDown(), + icon: opts.pagination ? opts.icons.paginationSwitchDown : opts.icons.paginationSwitchUp, + render: false, + event: this.togglePagination, + attributes: { + 'aria-label': opts.formatPaginationSwitch(), + title: opts.formatPaginationSwitch() } + }, + refresh: { + text: opts.formatRefresh(), + icon: opts.icons.refresh, + render: false, + event: this.refresh, + attributes: { + 'aria-label': opts.formatRefresh(), + title: opts.formatRefresh() + } + }, + toggle: { + text: opts.formatToggle(), + icon: opts.icons.toggleOff, + render: false, + event: this.toggleView, + attributes: { + 'aria-label': opts.formatToggleOn(), + title: opts.formatToggleOn() + } + }, + fullscreen: { + text: opts.formatFullscreen(), + icon: opts.icons.fullscreen, + render: false, + event: this.toggleFullscreen, + attributes: { + 'aria-label': opts.formatFullscreen(), + title: opts.formatFullscreen() + } + }, + columns: { + render: false, + html: function html() { + var html = []; + html.push("
    \n \n ").concat(_this4.constants.html.toolbarDropdown[0])); - _this8.trigger(type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td); - _this8.trigger(type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr, field); + if (opts.showColumnsSearch) { + html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf('', _this4.constants.classes.input, opts.formatSearch()))); + html.push(_this4.constants.html.toolbarDropdownSeparator); + } - // if click to select - then trigger the checkbox/radio click - if (type === 'click' && _this8.options.clickToSelect && column.clickToSelect && !Utils.calculateObjectValue(_this8.options, _this8.options.ignoreClickToSelectOn, [target])) { - var $selectItem = $tr.find(Utils.sprintf('[name="%s"]', _this8.options.selectItemName)); - if ($selectItem.length) { - $selectItem[0].click(); // #144: .trigger('click') bug + if (opts.showColumnsToggleAll) { + var allFieldsVisible = _this4.getVisibleColumns().length === _this4.columns.filter(function (column) { + return !_this4.isSelectionColumn(column); + }).length; + + html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf(' %s', allFieldsVisible ? 'checked="checked"' : '', opts.formatColumnsToggleAll()))); + html.push(_this4.constants.html.toolbarDropdownSeparator); + } + + var visibleColumns = 0; + + _this4.columns.forEach(function (column) { + if (column.visible) { + visibleColumns++; + } + }); + + _this4.columns.forEach(function (column, i) { + if (_this4.isSelectionColumn(column)) { + return; + } + + if (opts.cardView && !column.cardVisible) { + return; + } + + var checked = column.visible ? ' checked="checked"' : ''; + var disabled = visibleColumns <= opts.minimumCountColumns && checked ? ' disabled="disabled"' : ''; + + if (column.switchable) { + html.push(Utils.sprintf(_this4.constants.html.toolbarDropdownItem, Utils.sprintf(' %s', column.field, i, checked, disabled, column.title))); + switchableCount++; + } + }); + + html.push(_this4.constants.html.toolbarDropdown[1], '
    '); + return html.join(''); + } + } + }); + var buttonsHtml = {}; + + for (var _i2 = 0, _Object$entries2 = Object.entries(this.buttons); _i2 < _Object$entries2.length; _i2++) { + var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), + buttonName = _Object$entries2$_i[0], + buttonConfig = _Object$entries2$_i[1]; + + var buttonHtml = void 0; + + if (buttonConfig.hasOwnProperty('html')) { + if (typeof buttonConfig.html === 'function') { + buttonHtml = buttonConfig.html(); + } else if (typeof buttonConfig.html === 'string') { + buttonHtml = buttonConfig.html; + } + } else { + buttonHtml = "'; + } + + buttonsHtml[buttonName] = buttonHtml; + var optionName = "show".concat(buttonName.charAt(0).toUpperCase()).concat(buttonName.substring(1)); + var showOption = opts[optionName]; + + if ((!buttonConfig.hasOwnProperty('render') || buttonConfig.hasOwnProperty('render') && buttonConfig.render) && (showOption === undefined || showOption === true)) { + opts[optionName] = true; + } + + if (!opts.buttonsOrder.includes(buttonName)) { + opts.buttonsOrder.push(buttonName); + } + } // Adding the button html to the final toolbar html when the showOption is true + + + var _iterator = _createForOfIteratorHelper(opts.buttonsOrder), + _step; + + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var button = _step.value; + var _showOption = opts["show".concat(button.charAt(0).toUpperCase()).concat(button.substring(1))]; + + if (_showOption) { + html.push(buttonsHtml[button]); + } + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + + html.push('
    '); // Fix #188: this.showToolbar is for extensions + + if (this.showToolbar || html.length > 2) { + this.$toolbar.append(html.join('')); + } + + for (var _i4 = 0, _Object$entries4 = Object.entries(this.buttons); _i4 < _Object$entries4.length; _i4++) { + var _Object$entries4$_i = _slicedToArray(_Object$entries4[_i4], 2), + _buttonName = _Object$entries4$_i[0], + _buttonConfig = _Object$entries4$_i[1]; + + if (_buttonConfig.hasOwnProperty('event')) { + if (typeof _buttonConfig.event === 'function' || typeof _buttonConfig.event === 'string') { + var _ret = function () { + var event = typeof _buttonConfig.event === 'string' ? window[_buttonConfig.event] : _buttonConfig.event; + + _this4.$toolbar.find("button[name=\"".concat(_buttonName, "\"]")).off('click').on('click', function () { + return event.call(_this4); + }); + + return "continue"; + }(); + + if (_ret === "continue") continue; } var _loop = function _loop() { - if (_isArray15) { - if (_i17 >= _iterator15.length) return 'break'; - _ref33 = _iterator15[_i17++]; - } else { - _i17 = _iterator15.next(); - if (_i17.done) return 'break'; - _ref33 = _i17.value; - } + var _Object$entries5$_i = _slicedToArray(_Object$entries5[_i5], 2), + eventType = _Object$entries5$_i[0], + eventFunction = _Object$entries5$_i[1]; - var _ref34 = _ref33, - _ref35 = _slicedToArray(_ref34, 2), - key = _ref35[0], - event = _ref35[1]; + var event = typeof eventFunction === 'string' ? window[eventFunction] : eventFunction; - _this8.$body.find('>tr:not(.no-records-found)').each(function (i, tr) { - var $tr = $(tr); - var $td = $tr.find(_this8.options.cardView ? '.card-view' : 'td').eq(fieldIndex); - var index = key.indexOf(' '); - var name = key.substring(0, index); - var el = key.substring(index + 1); - - $td.find(el).off(name).on(name, function (e) { - var index = $tr.data('index'); - var row = _this8.data[index]; - var value = row[field]; - - event.apply(_this8, [e, value, row, index]); - }); + _this4.$toolbar.find("button[name=\"".concat(_buttonName, "\"]")).off(eventType).on(eventType, function () { + return event.call(_this4); }); }; - for (var _iterator15 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(events), _isArray15 = Array.isArray(_iterator15), _i17 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) { - var _ref33; - - var _ret = _loop(); - - if (_ret === 'break') break; + for (var _i5 = 0, _Object$entries5 = Object.entries(_buttonConfig.event); _i5 < _Object$entries5.length; _i5++) { + _loop(); } + } + } + + if (opts.showColumns) { + $keepOpen = this.$toolbar.find('.keep-open'); + var $checkboxes = $keepOpen.find('input[type="checkbox"]:not(".toggle-all")'); + var $toggleAll = $keepOpen.find('input[type="checkbox"].toggle-all'); + + if (switchableCount <= opts.minimumCountColumns) { + $keepOpen.find('input').prop('disabled', true); + } + + $keepOpen.find('li, label').off('click').on('click', function (e) { + e.stopImmediatePropagation(); + }); + $checkboxes.off('click').on('click', function (_ref2) { + var currentTarget = _ref2.currentTarget; + var $this = $__default['default'](currentTarget); + + _this4._toggleColumn($this.val(), $this.prop('checked'), false); + + _this4.trigger('column-switch', $this.data('field'), $this.prop('checked')); + + $toggleAll.prop('checked', $checkboxes.filter(':checked').length === _this4.columns.filter(function (column) { + return !_this4.isSelectionColumn(column); + }).length); + }); + $toggleAll.off('click').on('click', function (_ref3) { + var currentTarget = _ref3.currentTarget; + + _this4._toggleAllColumns($__default['default'](currentTarget).prop('checked')); }); - this.updateSelected(); - this.resetView(); + if (opts.showColumnsSearch) { + var $columnsSearch = $keepOpen.find('[name="columnsSearch"]'); + var $listItems = $keepOpen.find('.dropdown-item-marker'); + $columnsSearch.on('keyup paste change', function (_ref4) { + var currentTarget = _ref4.currentTarget; + var $this = $__default['default'](currentTarget); + var searchValue = $this.val().toLowerCase(); + $listItems.show(); + $checkboxes.each(function (i, el) { + var $checkbox = $__default['default'](el); + var $listItem = $checkbox.parents('.dropdown-item-marker'); + var text = $listItem.text().toLowerCase(); - this.trigger('post-body', data); + if (!text.includes(searchValue)) { + $listItem.hide(); + } + }); + }); + } } - }, { - key: 'initServer', - value: function initServer(silent, query, url) { - var _this9 = this; - var data = {}; - var index = this.header.fields.indexOf(this.options.sortName); + var handleInputEvent = function handleInputEvent($searchInput) { + var eventTriggers = 'keyup drop blur mouseup'; + $searchInput.off(eventTriggers).on(eventTriggers, function (event) { + if (opts.searchOnEnterKey && event.keyCode !== 13) { + return; + } - var params = { - searchText: this.searchText, - sortName: this.options.sortName, - sortOrder: this.options.sortOrder + if ([37, 38, 39, 40].includes(event.keyCode)) { + return; + } + + clearTimeout(timeoutId); // doesn't matter if it's 0 + + timeoutId = setTimeout(function () { + _this4.onSearch({ + currentTarget: event.currentTarget + }); + }, opts.searchTimeOut); + }); + }; // Fix #4516: this.showSearchClearButton is for extensions + + + if ((opts.search || this.showSearchClearButton) && typeof opts.searchSelector !== 'string') { + html = []; + var showSearchButton = Utils.sprintf(this.constants.html.searchButton, this.constants.buttonsClass, opts.formatSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.search) : '', opts.showButtonText ? opts.formatSearch() : ''); + var showSearchClearButton = Utils.sprintf(this.constants.html.searchClearButton, this.constants.buttonsClass, opts.formatClearSearch(), opts.showButtonIcons ? Utils.sprintf(this.constants.html.icon, opts.iconsPrefix, opts.icons.clearSearch) : '', opts.showButtonText ? opts.formatClearSearch() : ''); + var searchInputHtml = ""); + var searchInputFinalHtml = searchInputHtml; + + if (opts.showSearchButton || opts.showSearchClearButton) { + var _buttonsHtml = (opts.showSearchButton ? showSearchButton : '') + (opts.showSearchClearButton ? showSearchClearButton : ''); + + searchInputFinalHtml = opts.search ? Utils.sprintf(this.constants.html.inputGroup, searchInputHtml, _buttonsHtml) : _buttonsHtml; + } + + html.push(Utils.sprintf("\n
    \n %s\n
    \n "), searchInputFinalHtml)); + this.$toolbar.append(html.join('')); + var $searchInput = Utils.getSearchInput(this); + + if (opts.showSearchButton) { + this.$toolbar.find('.search button[name=search]').off('click').on('click', function () { + clearTimeout(timeoutId); // doesn't matter if it's 0 + + timeoutId = setTimeout(function () { + _this4.onSearch({ + currentTarget: $searchInput + }); + }, opts.searchTimeOut); + }); + + if (opts.searchOnEnterKey) { + handleInputEvent($searchInput); + } + } else { + handleInputEvent($searchInput); + } + + if (opts.showSearchClearButton) { + this.$toolbar.find('.search button[name=clearSearch]').click(function () { + _this4.resetSearch(); + }); + } + } else if (typeof opts.searchSelector === 'string') { + var _$searchInput = Utils.getSearchInput(this); + + handleInputEvent(_$searchInput); + } + } + }, { + key: "onSearch", + value: function onSearch() { + var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + currentTarget = _ref5.currentTarget, + firedByInitSearchText = _ref5.firedByInitSearchText; + + var overwriteSearchText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + + if (currentTarget !== undefined && $__default['default'](currentTarget).length && overwriteSearchText) { + var text = $__default['default'](currentTarget).val().trim(); + + if (this.options.trimOnSearch && $__default['default'](currentTarget).val() !== text) { + $__default['default'](currentTarget).val(text); + } + + if (this.searchText === text) { + return; + } + + if (currentTarget === Utils.getSearchInput(this)[0] || $__default['default'](currentTarget).hasClass('search-input')) { + this.searchText = text; + this.options.searchText = text; + } + } + + if (!firedByInitSearchText) { + this.options.pageNumber = 1; + } + + this.initSearch(); + + if (firedByInitSearchText) { + if (this.options.sidePagination === 'client') { + this.updatePagination(); + } + } else { + this.updatePagination(); + } + + this.trigger('search', this.searchText); + } + }, { + key: "initSearch", + value: function initSearch() { + var _this5 = this; + + this.filterOptions = this.filterOptions || this.options.filterOptions; + + if (this.options.sidePagination !== 'server') { + if (this.options.customSearch) { + this.data = Utils.calculateObjectValue(this.options, this.options.customSearch, [this.options.data, this.searchText, this.filterColumns]); + + if (this.options.sortReset) { + this.unsortedData = _toConsumableArray(this.data); + } + + return; + } + + var s = this.searchText && (this.fromHtml ? Utils.escapeHTML(this.searchText) : this.searchText).toLowerCase(); + var f = Utils.isEmptyObject(this.filterColumns) ? null : this.filterColumns; + + if (this.options.searchAccentNeutralise) { + s = Utils.normalizeAccent(s); + } // Check filter + + + if (typeof this.filterOptions.filterAlgorithm === 'function') { + this.data = this.options.data.filter(function (item) { + return _this5.filterOptions.filterAlgorithm.apply(null, [item, f]); + }); + } else if (typeof this.filterOptions.filterAlgorithm === 'string') { + this.data = f ? this.options.data.filter(function (item) { + var filterAlgorithm = _this5.filterOptions.filterAlgorithm; + + if (filterAlgorithm === 'and') { + for (var key in f) { + if (Array.isArray(f[key]) && !f[key].includes(item[key]) || !Array.isArray(f[key]) && item[key] !== f[key]) { + return false; + } + } + } else if (filterAlgorithm === 'or') { + var match = false; + + for (var _key in f) { + if (Array.isArray(f[_key]) && f[_key].includes(item[_key]) || !Array.isArray(f[_key]) && item[_key] === f[_key]) { + match = true; + } + } + + return match; + } + + return true; + }) : _toConsumableArray(this.options.data); + } + + var visibleFields = this.getVisibleFields(); + this.data = s ? this.data.filter(function (item, i) { + for (var j = 0; j < _this5.header.fields.length; j++) { + if (!_this5.header.searchables[j] || _this5.options.visibleSearch && visibleFields.indexOf(_this5.header.fields[j]) === -1) { + continue; + } + + var key = Utils.isNumeric(_this5.header.fields[j]) ? parseInt(_this5.header.fields[j], 10) : _this5.header.fields[j]; + var column = _this5.columns[_this5.fieldsColumnsIndex[key]]; + var value = void 0; + + if (typeof key === 'string') { + value = item; + var props = key.split('.'); + + for (var _i6 = 0; _i6 < props.length; _i6++) { + if (value[props[_i6]] !== null) { + value = value[props[_i6]]; + } + } + } else { + value = item[key]; + } + + if (_this5.options.searchAccentNeutralise) { + value = Utils.normalizeAccent(value); + } // Fix #142: respect searchFormatter boolean + + + if (column && column.searchFormatter) { + value = Utils.calculateObjectValue(column, _this5.header.formatters[j], [value, item, i, column.field], value); + } + + if (typeof value === 'string' || typeof value === 'number') { + if (_this5.options.strictSearch) { + if ("".concat(value).toLowerCase() === s) { + return true; + } + } else { + var largerSmallerEqualsRegex = /(?:(<=|=>|=<|>=|>|<)(?:\s+)?(-?\d+)?|(-?\d+)?(\s+)?(<=|=>|=<|>=|>|<))/gm; + var matches = largerSmallerEqualsRegex.exec(_this5.searchText); + var comparisonCheck = false; + + if (matches) { + var operator = matches[1] || "".concat(matches[5], "l"); + var comparisonValue = matches[2] || matches[3]; + var int = parseInt(value, 10); + var comparisonInt = parseInt(comparisonValue, 10); + + switch (operator) { + case '>': + case ' comparisonInt; + break; + + case '<': + case '>l': + comparisonCheck = int < comparisonInt; + break; + + case '<=': + case '=<': + case '>=l': + case '=>l': + comparisonCheck = int <= comparisonInt; + break; + + case '>=': + case '=>': + case '<=l': + case '== comparisonInt; + break; + } + } + + if (comparisonCheck || "".concat(value).toLowerCase().includes(s)) { + return true; + } + } + } + } + + return false; + }) : this.data; + + if (this.options.sortReset) { + this.unsortedData = _toConsumableArray(this.data); + } + + this.initSort(); + } + } + }, { + key: "initPagination", + value: function initPagination() { + var _this6 = this; + + var opts = this.options; + + if (!opts.pagination) { + this.$pagination.hide(); + return; + } + + this.$pagination.show(); + var html = []; + var allSelected = false; + var i; + var from; + var to; + var $pageList; + var $pre; + var $next; + var $number; + var data = this.getData({ + includeHiddenRows: false + }); + var pageList = opts.pageList; + + if (typeof pageList === 'string') { + pageList = pageList.replace(/\[|\]| /g, '').toLowerCase().split(','); + } + + pageList = pageList.map(function (value) { + if (typeof value === 'string') { + return value.toLowerCase() === opts.formatAllRows().toLowerCase() || ['all', 'unlimited'].includes(value.toLowerCase()) ? opts.formatAllRows() : +value; + } + + return value; + }); + this.paginationParts = opts.paginationParts; + + if (typeof this.paginationParts === 'string') { + this.paginationParts = this.paginationParts.replace(/\[|\]| |'/g, '').split(','); + } + + if (opts.sidePagination !== 'server') { + opts.totalRows = data.length; + } + + this.totalPages = 0; + + if (opts.totalRows) { + if (opts.pageSize === opts.formatAllRows()) { + opts.pageSize = opts.totalRows; + allSelected = true; + } + + this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1; + opts.totalPages = this.totalPages; + } + + if (this.totalPages > 0 && opts.pageNumber > this.totalPages) { + opts.pageNumber = this.totalPages; + } + + this.pageFrom = (opts.pageNumber - 1) * opts.pageSize + 1; + this.pageTo = opts.pageNumber * opts.pageSize; + + if (this.pageTo > opts.totalRows) { + this.pageTo = opts.totalRows; + } + + if (this.options.pagination && this.options.sidePagination !== 'server') { + this.options.totalNotFiltered = this.options.data.length; + } + + if (!this.options.showExtendedPagination) { + this.options.totalNotFiltered = undefined; + } + + if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) { + html.push("
    ")); + } + + if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) { + var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(opts.totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, opts.totalRows, opts.totalNotFiltered); + html.push("\n ".concat(paginationInfo, "\n ")); + } + + if (this.paginationParts.includes('pageSize')) { + html.push('
    '); + var pageNumber = ["
    \n \n ").concat(this.constants.html.pageDropdown[0])]; + pageList.forEach(function (page, i) { + if (!opts.smartDisplay || i === 0 || pageList[i - 1] < opts.totalRows || page === opts.formatAllRows()) { + var active; + + if (allSelected) { + active = page === opts.formatAllRows() ? _this6.constants.classes.dropdownActive : ''; + } else { + active = page === opts.pageSize ? _this6.constants.classes.dropdownActive : ''; + } + + pageNumber.push(Utils.sprintf(_this6.constants.html.pageDropdownItem, active, page)); + } + }); + pageNumber.push("".concat(this.constants.html.pageDropdown[1], "
    ")); + html.push(opts.formatRecordsPerPage(pageNumber.join(''))); + } + + if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort') || this.paginationParts.includes('pageSize')) { + html.push('
    '); + } + + if (this.paginationParts.includes('pageList')) { + html.push("
    "), Utils.sprintf(this.constants.html.pagination[0], Utils.sprintf(' pagination-%s', opts.iconSize)), Utils.sprintf(this.constants.html.paginationItem, ' page-pre', opts.formatSRPaginationPreText(), opts.paginationPreText)); + + if (this.totalPages < opts.paginationSuccessivelySize) { + from = 1; + to = this.totalPages; + } else { + from = opts.pageNumber - opts.paginationPagesBySide; + to = from + opts.paginationPagesBySide * 2; + } + + if (opts.pageNumber < opts.paginationSuccessivelySize - 1) { + to = opts.paginationSuccessivelySize; + } + + if (opts.paginationSuccessivelySize > this.totalPages - from) { + from = from - (opts.paginationSuccessivelySize - (this.totalPages - from)) + 1; + } + + if (from < 1) { + from = 1; + } + + if (to > this.totalPages) { + to = this.totalPages; + } + + var middleSize = Math.round(opts.paginationPagesBySide / 2); + + var pageItem = function pageItem(i) { + var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + return Utils.sprintf(_this6.constants.html.paginationItem, classes + (i === opts.pageNumber ? " ".concat(_this6.constants.classes.paginationActive) : ''), opts.formatSRPaginationPageText(i), i); }; - if (this.header.sortNames[index]) { - params.sortName = this.header.sortNames[index]; + if (from > 1) { + var max = opts.paginationPagesBySide; + if (max >= from) max = from - 1; + + for (i = 1; i <= max; i++) { + html.push(pageItem(i)); + } + + if (from - 1 === max + 1) { + i = from - 1; + html.push(pageItem(i)); + } else if (from - 1 > max) { + if (from - opts.paginationPagesBySide * 2 > opts.paginationPagesBySide && opts.paginationUseIntermediate) { + i = Math.round((from - middleSize) / 2 + middleSize); + html.push(pageItem(i, ' page-intermediate')); + } else { + html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-first-separator disabled', '', '...')); + } + } } + for (i = from; i <= to; i++) { + html.push(pageItem(i)); + } + + if (this.totalPages > to) { + var min = this.totalPages - (opts.paginationPagesBySide - 1); + if (to >= min) min = to + 1; + + if (to + 1 === min - 1) { + i = to + 1; + html.push(pageItem(i)); + } else if (min > to + 1) { + if (this.totalPages - to > opts.paginationPagesBySide * 2 && opts.paginationUseIntermediate) { + i = Math.round((this.totalPages - middleSize - to) / 2 + to); + html.push(pageItem(i, ' page-intermediate')); + } else { + html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-last-separator disabled', '', '...')); + } + } + + for (i = min; i <= this.totalPages; i++) { + html.push(pageItem(i)); + } + } + + html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-next', opts.formatSRPaginationNextText(), opts.paginationNextText)); + html.push(this.constants.html.pagination[1], '
    '); + } + + this.$pagination.html(html.join('')); + var dropupClass = ['bottom', 'both'].includes(opts.paginationVAlign) ? " ".concat(this.constants.classes.dropup) : ''; + this.$pagination.last().find('.page-list > div').addClass(dropupClass); + + if (!opts.onlyInfoPagination) { + $pageList = this.$pagination.find('.page-list a'); + $pre = this.$pagination.find('.page-pre'); + $next = this.$pagination.find('.page-next'); + $number = this.$pagination.find('.page-item').not('.page-next, .page-pre, .page-last-separator, .page-first-separator'); + + if (this.totalPages <= 1) { + this.$pagination.find('div.pagination').hide(); + } + + if (opts.smartDisplay) { + if (pageList.length < 2 || opts.totalRows <= pageList[0]) { + this.$pagination.find('span.page-list').hide(); + } + } // when data is empty, hide the pagination + + + this.$pagination[this.getData().length ? 'show' : 'hide'](); + + if (!opts.paginationLoop) { + if (opts.pageNumber === 1) { + $pre.addClass('disabled'); + } + + if (opts.pageNumber === this.totalPages) { + $next.addClass('disabled'); + } + } + + if (allSelected) { + opts.pageSize = opts.formatAllRows(); + } // removed the events for last and first, onPageNumber executeds the same logic + + + $pageList.off('click').on('click', function (e) { + return _this6.onPageListChange(e); + }); + $pre.off('click').on('click', function (e) { + return _this6.onPagePre(e); + }); + $next.off('click').on('click', function (e) { + return _this6.onPageNext(e); + }); + $number.off('click').on('click', function (e) { + return _this6.onPageNumber(e); + }); + } + } + }, { + key: "updatePagination", + value: function updatePagination(event) { + // Fix #171: IE disabled button can be clicked bug. + if (event && $__default['default'](event.currentTarget).hasClass('disabled')) { + return; + } + + if (!this.options.maintainMetaData) { + this.resetRows(); + } + + this.initPagination(); + this.trigger('page-change', this.options.pageNumber, this.options.pageSize); + + if (this.options.sidePagination === 'server') { + this.initServer(); + } else { + this.initBody(); + } + } + }, { + key: "onPageListChange", + value: function onPageListChange(event) { + event.preventDefault(); + var $this = $__default['default'](event.currentTarget); + $this.parent().addClass(this.constants.classes.dropdownActive).siblings().removeClass(this.constants.classes.dropdownActive); + this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? this.options.formatAllRows() : +$this.text(); + this.$toolbar.find('.page-size').text(this.options.pageSize); + this.updatePagination(event); + return false; + } + }, { + key: "onPagePre", + value: function onPagePre(event) { + event.preventDefault(); + + if (this.options.pageNumber - 1 === 0) { + this.options.pageNumber = this.options.totalPages; + } else { + this.options.pageNumber--; + } + + this.updatePagination(event); + return false; + } + }, { + key: "onPageNext", + value: function onPageNext(event) { + event.preventDefault(); + + if (this.options.pageNumber + 1 > this.options.totalPages) { + this.options.pageNumber = 1; + } else { + this.options.pageNumber++; + } + + this.updatePagination(event); + return false; + } + }, { + key: "onPageNumber", + value: function onPageNumber(event) { + event.preventDefault(); + + if (this.options.pageNumber === +$__default['default'](event.currentTarget).text()) { + return; + } + + this.options.pageNumber = +$__default['default'](event.currentTarget).text(); + this.updatePagination(event); + return false; + } // eslint-disable-next-line no-unused-vars + + }, { + key: "initRow", + value: function initRow(item, i, data, trFragments) { + var _this7 = this; + + var html = []; + var style = {}; + var csses = []; + var data_ = ''; + var attributes = {}; + var htmlAttributes = []; + + if (Utils.findIndex(this.hiddenRows, item) > -1) { + return; + } + + style = Utils.calculateObjectValue(this.options, this.options.rowStyle, [item, i], style); + + if (style && style.css) { + for (var _i7 = 0, _Object$entries6 = Object.entries(style.css); _i7 < _Object$entries6.length; _i7++) { + var _Object$entries6$_i = _slicedToArray(_Object$entries6[_i7], 2), + key = _Object$entries6$_i[0], + value = _Object$entries6$_i[1]; + + csses.push("".concat(key, ": ").concat(value)); + } + } + + attributes = Utils.calculateObjectValue(this.options, this.options.rowAttributes, [item, i], attributes); + + if (attributes) { + for (var _i8 = 0, _Object$entries7 = Object.entries(attributes); _i8 < _Object$entries7.length; _i8++) { + var _Object$entries7$_i = _slicedToArray(_Object$entries7[_i8], 2), + _key2 = _Object$entries7$_i[0], + _value = _Object$entries7$_i[1]; + + htmlAttributes.push("".concat(_key2, "=\"").concat(Utils.escapeHTML(_value), "\"")); + } + } + + if (item._data && !Utils.isEmptyObject(item._data)) { + for (var _i9 = 0, _Object$entries8 = Object.entries(item._data); _i9 < _Object$entries8.length; _i9++) { + var _Object$entries8$_i = _slicedToArray(_Object$entries8[_i9], 2), + k = _Object$entries8$_i[0], + v = _Object$entries8$_i[1]; + + // ignore data-index + if (k === 'index') { + return; + } + + data_ += " data-".concat(k, "='").concat(_typeof(v) === 'object' ? JSON.stringify(v) : v, "'"); + } + } + + html.push(''); + + if (this.options.cardView) { + html.push("
    ")); + } + + var detailViewTemplate = ''; + + if (Utils.hasDetailViewIcon(this.options)) { + detailViewTemplate = ''; + + if (Utils.calculateObjectValue(null, this.options.detailFilter, [i, item])) { + detailViewTemplate += "\n \n ".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen), "\n \n "); + } + + detailViewTemplate += ''; + } + + if (detailViewTemplate && this.options.detailViewAlign !== 'right') { + html.push(detailViewTemplate); + } + + this.header.fields.forEach(function (field, j) { + var text = ''; + var value_ = Utils.getItemField(item, field, _this7.options.escape); + var value = ''; + var type = ''; + var cellStyle = {}; + var id_ = ''; + var class_ = _this7.header.classes[j]; + var style_ = ''; + var styleToAdd_ = ''; + var data_ = ''; + var rowspan_ = ''; + var colspan_ = ''; + var title_ = ''; + var column = _this7.columns[j]; + + if ((_this7.fromHtml || _this7.autoMergeCells) && typeof value_ === 'undefined') { + if (!column.checkbox && !column.radio) { + return; + } + } + + if (!column.visible) { + return; + } + + if (_this7.options.cardView && !column.cardVisible) { + return; + } + + if (column.escape) { + value_ = Utils.escapeHTML(value_); + } // Style concat + + + if (csses.concat([_this7.header.styles[j]]).length) { + styleToAdd_ += "".concat(csses.concat([_this7.header.styles[j]]).join('; ')); + } + + if (item["_".concat(field, "_style")]) { + styleToAdd_ += "".concat(item["_".concat(field, "_style")]); + } + + if (styleToAdd_) { + style_ = " style=\"".concat(styleToAdd_, "\""); + } // Style concat + // handle id and class of td + + + if (item["_".concat(field, "_id")]) { + id_ = Utils.sprintf(' id="%s"', item["_".concat(field, "_id")]); + } + + if (item["_".concat(field, "_class")]) { + class_ = Utils.sprintf(' class="%s"', item["_".concat(field, "_class")]); + } + + if (item["_".concat(field, "_rowspan")]) { + rowspan_ = Utils.sprintf(' rowspan="%s"', item["_".concat(field, "_rowspan")]); + } + + if (item["_".concat(field, "_colspan")]) { + colspan_ = Utils.sprintf(' colspan="%s"', item["_".concat(field, "_colspan")]); + } + + if (item["_".concat(field, "_title")]) { + title_ = Utils.sprintf(' title="%s"', item["_".concat(field, "_title")]); + } + + cellStyle = Utils.calculateObjectValue(_this7.header, _this7.header.cellStyles[j], [value_, item, i, field], cellStyle); + + if (cellStyle.classes) { + class_ = " class=\"".concat(cellStyle.classes, "\""); + } + + if (cellStyle.css) { + var csses_ = []; + + for (var _i10 = 0, _Object$entries9 = Object.entries(cellStyle.css); _i10 < _Object$entries9.length; _i10++) { + var _Object$entries9$_i = _slicedToArray(_Object$entries9[_i10], 2), + _key3 = _Object$entries9$_i[0], + _value2 = _Object$entries9$_i[1]; + + csses_.push("".concat(_key3, ": ").concat(_value2)); + } + + style_ = " style=\"".concat(csses_.concat(_this7.header.styles[j]).join('; '), "\""); + } + + value = Utils.calculateObjectValue(column, _this7.header.formatters[j], [value_, item, i, field], value_); + + if (!(column.checkbox || column.radio)) { + value = typeof value === 'undefined' || value === null ? _this7.options.undefinedText : value; + } + + if (column.searchable && _this7.searchText && _this7.options.searchHighlight) { + var defValue = ''; + var regExp = new RegExp("(".concat(_this7.searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), ")"), 'gim'); + var marker = '$1'; + var isHTML = value && /<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i.test(value); + + if (isHTML) { + // value can contains a HTML tags + var textContent = new DOMParser().parseFromString(value.toString(), 'text/html').documentElement.textContent; + var textReplaced = textContent.replace(regExp, marker); + defValue = value.replace(new RegExp("(>\\s*)(".concat(textContent, ")(\\s*)"), 'gm'), "$1".concat(textReplaced, "$3")); + } else { + // but usually not + defValue = value.toString().replace(regExp, marker); + } + + value = Utils.calculateObjectValue(column, column.searchHighlightFormatter, [value, _this7.searchText], defValue); + } + + if (item["_".concat(field, "_data")] && !Utils.isEmptyObject(item["_".concat(field, "_data")])) { + for (var _i11 = 0, _Object$entries10 = Object.entries(item["_".concat(field, "_data")]); _i11 < _Object$entries10.length; _i11++) { + var _Object$entries10$_i = _slicedToArray(_Object$entries10[_i11], 2), + _k = _Object$entries10$_i[0], + _v = _Object$entries10$_i[1]; + + // ignore data-index + if (_k === 'index') { + return; + } + + data_ += " data-".concat(_k, "=\"").concat(_v, "\""); + } + } + + if (column.checkbox || column.radio) { + type = column.checkbox ? 'checkbox' : type; + type = column.radio ? 'radio' : type; + var c = column['class'] || ''; + var isChecked = Utils.isObject(value) && value.hasOwnProperty('checked') ? value.checked : (value === true || value_) && value !== false; + var isDisabled = !column.checkboxEnabled || value && value.disabled; + text = [_this7.options.cardView ? "
    ") : ""), ""), _this7.header.formatters[j] && typeof value === 'string' ? value : '', _this7.options.cardView ? '
    ' : ''].join(''); + item[_this7.header.stateField] = value === true || !!value_ || value && value.checked; + } else if (_this7.options.cardView) { + var cardTitle = _this7.options.showHeader ? "").concat(Utils.getFieldTitle(_this7.columns, field), "") : ''; + text = "
    ".concat(cardTitle, "").concat(value, "
    "); + + if (_this7.options.smartDisplay && value === '') { + text = '
    '; + } + } else { + text = "").concat(value, ""); + } + + html.push(text); + }); + + if (detailViewTemplate && this.options.detailViewAlign === 'right') { + html.push(detailViewTemplate); + } + + if (this.options.cardView) { + html.push('
    '); + } + + html.push(''); + return html.join(''); + } + }, { + key: "initBody", + value: function initBody(fixedScroll) { + var _this8 = this; + + var data = this.getData(); + this.trigger('pre-body', data); + this.$body = this.$el.find('>tbody'); + + if (!this.$body.length) { + this.$body = $__default['default']('').appendTo(this.$el); + } // Fix #389 Bootstrap-table-flatJSON is not working + + + if (!this.options.pagination || this.options.sidePagination === 'server') { + this.pageFrom = 1; + this.pageTo = data.length; + } + + var rows = []; + var trFragments = $__default['default'](document.createDocumentFragment()); + var hasTr = false; + this.autoMergeCells = Utils.checkAutoMergeCells(data.slice(this.pageFrom - 1, this.pageTo)); + + for (var i = this.pageFrom - 1; i < this.pageTo; i++) { + var item = data[i]; + var tr = this.initRow(item, i, data, trFragments); + hasTr = hasTr || !!tr; + + if (tr && typeof tr === 'string') { + if (!this.options.virtualScroll) { + trFragments.append(tr); + } else { + rows.push(tr); + } + } + } // show no records + + + if (!hasTr) { + this.$body.html("".concat(Utils.sprintf('%s', this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options), this.options.formatNoMatches()), "")); + } else if (!this.options.virtualScroll) { + this.$body.html(trFragments); + } else { + if (this.virtualScroll) { + this.virtualScroll.destroy(); + } + + this.virtualScroll = new VirtualScroll({ + rows: rows, + fixedScroll: fixedScroll, + scrollEl: this.$tableBody[0], + contentEl: this.$body[0], + itemHeight: this.options.virtualScrollItemHeight, + callback: function callback() { + _this8.fitHeader(); + + _this8.initBodyEvent(); + } + }); + } + + if (!fixedScroll) { + this.scrollTo(0); + } + + this.initBodyEvent(); + this.updateSelected(); + this.initFooter(); + this.resetView(); + + if (this.options.sidePagination !== 'server') { + this.options.totalRows = data.length; + } + + this.trigger('post-body', data); + } + }, { + key: "initBodyEvent", + value: function initBodyEvent() { + var _this9 = this; + + // click to select by column + this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) { + var $td = $__default['default'](e.currentTarget); + var $tr = $td.parent(); + var $cardViewArr = $__default['default'](e.target).parents('.card-views').children(); + var $cardViewTarget = $__default['default'](e.target).parents('.card-view'); + var rowIndex = $tr.data('index'); + var item = _this9.data[rowIndex]; + var index = _this9.options.cardView ? $cardViewArr.index($cardViewTarget) : $td[0].cellIndex; + + var fields = _this9.getVisibleFields(); + + var field = fields[index - Utils.getDetailViewIndexOffset(_this9.options)]; + var column = _this9.columns[_this9.fieldsColumnsIndex[field]]; + var value = Utils.getItemField(item, field, _this9.options.escape); + + if ($td.find('.detail-icon').length) { + return; + } + + _this9.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td); + + _this9.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr, field); // if click to select - then trigger the checkbox/radio click + + + if (e.type === 'click' && _this9.options.clickToSelect && column.clickToSelect && !Utils.calculateObjectValue(_this9.options, _this9.options.ignoreClickToSelectOn, [e.target])) { + var $selectItem = $tr.find(Utils.sprintf('[name="%s"]', _this9.options.selectItemName)); + + if ($selectItem.length) { + $selectItem[0].click(); + } + } + + if (e.type === 'click' && _this9.options.detailViewByClick) { + _this9.toggleDetailView(rowIndex, _this9.header.detailFormatters[_this9.fieldsColumnsIndex[field]]); + } + }).off('mousedown').on('mousedown', function (e) { + // https://github.com/jquery/jquery/issues/1741 + _this9.multipleSelectRowCtrlKey = e.ctrlKey || e.metaKey; + _this9.multipleSelectRowShiftKey = e.shiftKey; + }); + this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function (e) { + e.preventDefault(); + + _this9.toggleDetailView($__default['default'](e.currentTarget).parent().parent().data('index')); + + return false; + }); + this.$selectItem = this.$body.find(Utils.sprintf('[name="%s"]', this.options.selectItemName)); + this.$selectItem.off('click').on('click', function (e) { + e.stopImmediatePropagation(); + var $this = $__default['default'](e.currentTarget); + + _this9._toggleCheck($this.prop('checked'), $this.data('index')); + }); + this.header.events.forEach(function (_events, i) { + var events = _events; + + if (!events) { + return; + } // fix bug, if events is defined with namespace + + + if (typeof events === 'string') { + events = Utils.calculateObjectValue(null, events); + } + + var field = _this9.header.fields[i]; + + var fieldIndex = _this9.getVisibleFields().indexOf(field); + + if (fieldIndex === -1) { + return; + } + + fieldIndex += Utils.getDetailViewIndexOffset(_this9.options); + + var _loop2 = function _loop2(key) { + if (!events.hasOwnProperty(key)) { + return "continue"; + } + + var event = events[key]; + + _this9.$body.find('>tr:not(.no-records-found)').each(function (i, tr) { + var $tr = $__default['default'](tr); + var $td = $tr.find(_this9.options.cardView ? '.card-views>.card-view' : '>td').eq(fieldIndex); + var index = key.indexOf(' '); + var name = key.substring(0, index); + var el = key.substring(index + 1); + $td.find(el).off(name).on(name, function (e) { + var index = $tr.data('index'); + var row = _this9.data[index]; + var value = row[field]; + event.apply(_this9, [e, value, row, index]); + }); + }); + }; + + for (var key in events) { + var _ret2 = _loop2(key); + + if (_ret2 === "continue") continue; + } + }); + } + }, { + key: "initServer", + value: function initServer(silent, query, url) { + var _this10 = this; + + var data = {}; + var index = this.header.fields.indexOf(this.options.sortName); + var params = { + searchText: this.searchText, + sortName: this.options.sortName, + sortOrder: this.options.sortOrder + }; + + if (this.header.sortNames[index]) { + params.sortName = this.header.sortNames[index]; + } + + if (this.options.pagination && this.options.sidePagination === 'server') { + params.pageSize = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize; + params.pageNumber = this.options.pageNumber; + } + + if (!(url || this.options.url) && !this.options.ajax) { + return; + } + + if (this.options.queryParamsType === 'limit') { + params = { + search: params.searchText, + sort: params.sortName, + order: params.sortOrder + }; + if (this.options.pagination && this.options.sidePagination === 'server') { - params.pageSize = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize; - params.pageNumber = this.options.pageNumber; + params.offset = this.options.pageSize === this.options.formatAllRows() ? 0 : this.options.pageSize * (this.options.pageNumber - 1); + params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize; + + if (params.limit === 0) { + delete params.limit; + } } + } - if (!(url || this.options.url) && !this.options.ajax) { - return; - } + if (this.options.search && this.options.sidePagination === 'server' && this.columns.filter(function (column) { + return !column.searchable; + }).length) { + params.searchable = []; - if (this.options.queryParamsType === 'limit') { - params = { - search: params.searchText, - sort: params.sortName, - order: params.sortOrder - }; + var _iterator2 = _createForOfIteratorHelper(this.columns), + _step2; - if (this.options.pagination && this.options.sidePagination === 'server') { - params.offset = this.options.pageSize === this.options.formatAllRows() ? 0 : this.options.pageSize * (this.options.pageNumber - 1); - params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize; - if (params.limit === 0) { - delete params.limit; + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var column = _step2.value; + + if (!column.checkbox && column.searchable && (this.options.visibleSearch && column.visible || !this.options.visibleSearch)) { + params.searchable.push(column.field); } } - } - - if (!Utils.isEmptyObject(this.filterColumnsPartial)) { - params.filter = JSON.stringify(this.filterColumnsPartial, null); - } - - data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data); - - $.extend(data, query || {}); - - // false to stop request - if (data === false) { - return; - } - - if (!silent) { - this.showLoading(); - } - var request = $.extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), { - type: this.options.method, - url: url || this.options.url, - data: this.options.contentType === 'application/json' && this.options.method === 'post' ? JSON.stringify(data) : data, - cache: this.options.cache, - contentType: this.options.contentType, - dataType: this.options.dataType, - success: function success(_res) { - var res = Utils.calculateObjectValue(_this9.options, _this9.options.responseHandler, [_res], _res); - - _this9.load(res); - _this9.trigger('load-success', res); - if (!silent) { - _this9.hideLoading(); - } - }, - error: function error(jqXHR) { - var data = []; - if (_this9.options.sidePagination === 'server') { - data = {}; - data[_this9.options.totalField] = 0; - data[_this9.options.dataField] = []; - } - _this9.load(data); - _this9.trigger('load-error', jqXHR.status, jqXHR); - if (!silent) _this9.$tableLoading.hide(); - } - }); - - if (this.options.ajax) { - Utils.calculateObjectValue(this, this.options.ajax, [request], null); - } else { - if (this._xhr && this._xhr.readyState !== 4) { - this._xhr.abort(); - } - this._xhr = $.ajax(request); - } - - return data; - } - }, { - key: 'initSearchText', - value: function initSearchText() { - if (this.options.search) { - this.searchText = ''; - if (this.options.searchText !== '') { - var $search = this.$toolbar.find('.search input'); - $search.val(this.options.searchText); - this.onSearch({ currentTarget: $search, firedByInitSearchText: true }); - } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); } } - }, { - key: 'getCaret', - value: function getCaret() { - var _this10 = this; - this.$header.find('th').each(function (i, th) { - $(th).find('.sortable').removeClass('desc asc').addClass($(th).data('field') === _this10.options.sortName ? _this10.options.sortOrder : 'both'); - }); + if (!Utils.isEmptyObject(this.filterColumnsPartial)) { + params.filter = JSON.stringify(this.filterColumnsPartial, null); } - }, { - key: 'updateSelected', - value: function updateSelected() { - var checkAll = this.$selectItem.filter(':enabled').length && this.$selectItem.filter(':enabled').length === this.$selectItem.filter(':enabled').filter(':checked').length; - this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); + $__default['default'].extend(params, query || {}); + data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data); // false to stop request - this.$selectItem.each(function (i, el) { - $(el).closest('tr')[$(el).prop('checked') ? 'addClass' : 'removeClass']('selected'); - }); + if (data === false) { + return; } - }, { - key: 'updateRows', - value: function updateRows() { - var _this11 = this; - this.$selectItem.each(function (i, el) { - _this11.data[$(el).data('index')][_this11.header.stateField] = $(el).prop('checked'); - }); + if (!silent) { + this.showLoading(); } - }, { - key: 'resetRows', - value: function resetRows() { - for (var _iterator16 = this.data, _isArray16 = Array.isArray(_iterator16), _i18 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) { - var _ref36; - if (_isArray16) { - if (_i18 >= _iterator16.length) break; - _ref36 = _iterator16[_i18++]; - } else { - _i18 = _iterator16.next(); - if (_i18.done) break; - _ref36 = _i18.value; + var request = $__default['default'].extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), { + type: this.options.method, + url: url || this.options.url, + data: this.options.contentType === 'application/json' && this.options.method === 'post' ? JSON.stringify(data) : data, + cache: this.options.cache, + contentType: this.options.contentType, + dataType: this.options.dataType, + success: function success(_res, textStatus, jqXHR) { + var res = Utils.calculateObjectValue(_this10.options, _this10.options.responseHandler, [_res, jqXHR], _res); + + _this10.load(res); + + _this10.trigger('load-success', res, jqXHR && jqXHR.status, jqXHR); + + if (!silent) { + _this10.hideLoading(); } - var row = _ref36; + if (_this10.options.sidePagination === 'server' && res[_this10.options.totalField] > 0 && !res[_this10.options.dataField].length) { + _this10.updatePagination(); + } + }, + error: function error(jqXHR) { + var data = []; + if (_this10.options.sidePagination === 'server') { + data = {}; + data[_this10.options.totalField] = 0; + data[_this10.options.dataField] = []; + } + + _this10.load(data); + + _this10.trigger('load-error', jqXHR && jqXHR.status, jqXHR); + + if (!silent) _this10.$tableLoading.hide(); + } + }); + + if (this.options.ajax) { + Utils.calculateObjectValue(this, this.options.ajax, [request], null); + } else { + if (this._xhr && this._xhr.readyState !== 4) { + this._xhr.abort(); + } + + this._xhr = $__default['default'].ajax(request); + } + + return data; + } + }, { + key: "initSearchText", + value: function initSearchText() { + if (this.options.search) { + this.searchText = ''; + + if (this.options.searchText !== '') { + var $search = Utils.getSearchInput(this); + $search.val(this.options.searchText); + this.onSearch({ + currentTarget: $search, + firedByInitSearchText: true + }); + } + } + } + }, { + key: "getCaret", + value: function getCaret() { + var _this11 = this; + + this.$header.find('th').each(function (i, th) { + $__default['default'](th).find('.sortable').removeClass('desc asc').addClass($__default['default'](th).data('field') === _this11.options.sortName ? _this11.options.sortOrder : 'both'); + }); + } + }, { + key: "updateSelected", + value: function updateSelected() { + var checkAll = this.$selectItem.filter(':enabled').length && this.$selectItem.filter(':enabled').length === this.$selectItem.filter(':enabled').filter(':checked').length; + this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); + this.$selectItem.each(function (i, el) { + $__default['default'](el).closest('tr')[$__default['default'](el).prop('checked') ? 'addClass' : 'removeClass']('selected'); + }); + } + }, { + key: "updateRows", + value: function updateRows() { + var _this12 = this; + + this.$selectItem.each(function (i, el) { + _this12.data[$__default['default'](el).data('index')][_this12.header.stateField] = $__default['default'](el).prop('checked'); + }); + } + }, { + key: "resetRows", + value: function resetRows() { + var _iterator3 = _createForOfIteratorHelper(this.data), + _step3; + + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var row = _step3.value; this.$selectAll.prop('checked', false); this.$selectItem.prop('checked', false); + if (this.header.stateField) { row[this.header.stateField] = false; } } - this.initHiddenRows(); + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); } - }, { - key: 'trigger', - value: function trigger(_name) { - var _options; - var name = _name + '.bs.table'; + this.initHiddenRows(); + } + }, { + key: "trigger", + value: function trigger(_name) { + var _this$options, _this$options2; - for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key4 = 1; _key4 < _len2; _key4++) { - args[_key4 - 1] = arguments[_key4]; - } + var name = "".concat(_name, ".bs.table"); - (_options = this.options)[BootstrapTable.EVENTS[name]].apply(_options, args); - this.$el.trigger($.Event(name), args); - - this.options.onAll(name, args); - this.$el.trigger($.Event('all.bs.table'), [name, args]); + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key4 = 1; _key4 < _len; _key4++) { + args[_key4 - 1] = arguments[_key4]; } - }, { - key: 'resetHeader', - value: function resetHeader() { - var _this12 = this; - // fix #61: the hidden table reset header bug. - // fix bug: get $el.css('width') error sometime (height = 500) - clearTimeout(this.timeoutId_); + (_this$options = this.options)[BootstrapTable.EVENTS[name]].apply(_this$options, [].concat(args, [this])); + + this.$el.trigger($__default['default'].Event(name, { + sender: this + }), args); + + (_this$options2 = this.options).onAll.apply(_this$options2, [name].concat([].concat(args, [this]))); + + this.$el.trigger($__default['default'].Event('all.bs.table', { + sender: this + }), [name, args]); + } + }, { + key: "resetHeader", + value: function resetHeader() { + var _this13 = this; + + // fix #61: the hidden table reset header bug. + // fix bug: get $el.css('width') error sometime (height = 500) + clearTimeout(this.timeoutId_); + this.timeoutId_ = setTimeout(function () { + return _this13.fitHeader(); + }, this.$el.is(':hidden') ? 100 : 0); + } + }, { + key: "fitHeader", + value: function fitHeader() { + var _this14 = this; + + if (this.$el.is(':hidden')) { this.timeoutId_ = setTimeout(function () { - return _this12.fitHeader(); - }, this.$el.is(':hidden') ? 100 : 0); + return _this14.fitHeader(); + }, 100); + return; } - }, { - key: 'fitHeader', - value: function fitHeader() { - var _this13 = this; - if (this.$el.is(':hidden')) { - this.timeoutId_ = setTimeout(function () { - return _this13.fitHeader(); - }, 100); - return; - } + var fixedBody = this.$tableBody.get(0); + var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? Utils.getScrollBarWidth() : 0; + this.$el.css('margin-top', -this.$header.outerHeight()); + var focused = $__default['default'](':focus'); - var fixedBody = this.$tableBody.get(0); - var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? Utils.getScrollBarWidth() : 0; + if (focused.length > 0) { + var $th = focused.parents('th'); - this.$el.css('margin-top', -this.$header.outerHeight()); + if ($th.length > 0) { + var dataField = $th.attr('data-field'); - var focused = $(':focus'); - if (focused.length > 0) { - var $th = focused.parents('th'); - if ($th.length > 0) { - var dataField = $th.attr('data-field'); - if (dataField !== undefined) { - var $headerTh = this.$header.find('[data-field=\'' + dataField + '\']'); - if ($headerTh.length > 0) { - $headerTh.find(':input').addClass('focus-temp'); - } + if (dataField !== undefined) { + var $headerTh = this.$header.find("[data-field='".concat(dataField, "']")); + + if ($headerTh.length > 0) { + $headerTh.find(':input').addClass('focus-temp'); } } } + } - this.$header_ = this.$header.clone(true, true); - this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); - this.$tableHeader.css('margin-right', scrollWidth).find('table').css('width', this.$el.outerWidth()).html('').attr('class', this.$el.attr('class')).append(this.$header_); + this.$header_ = this.$header.clone(true, true); + this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); + this.$tableHeader.css('margin-right', scrollWidth).find('table').css('width', this.$el.outerWidth()).html('').attr('class', this.$el.attr('class')).append(this.$header_); + this.$tableLoading.css('width', this.$el.outerWidth()); + var focusedTemp = $__default['default']('.focus-temp:visible:eq(0)'); - this.$tableLoading.css('width', this.$el.outerWidth()); + if (focusedTemp.length > 0) { + focusedTemp.focus(); + this.$header.find('.focus-temp').removeClass('focus-temp'); + } // fix bug: $.data() is not working as expected after $.append() - var focusedTemp = $('.focus-temp:visible:eq(0)'); - if (focusedTemp.length > 0) { - focusedTemp.focus(); - this.$header.find('.focus-temp').removeClass('focus-temp'); - } - // fix bug: $.data() is not working as expected after $.append() - this.$header.find('th[data-field]').each(function (i, el) { - _this13.$header_.find(Utils.sprintf('th[data-field="%s"]', $(el).data('field'))).data($(el).data()); - }); + this.$header.find('th[data-field]').each(function (i, el) { + _this14.$header_.find(Utils.sprintf('th[data-field="%s"]', $__default['default'](el).data('field'))).data($__default['default'](el).data()); + }); + var visibleFields = this.getVisibleFields(); + var $ths = this.$header_.find('th'); + var $tr = this.$body.find('>tr:not(.no-records-found,.virtual-scroll-top)').eq(0); - var visibleFields = this.getVisibleFields(); - var $ths = this.$header_.find('th'); - var $tr = this.$body.find('>tr:first-child:not(.no-records-found)'); + while ($tr.length && $tr.find('>td[colspan]:not([colspan="1"])').length) { + $tr = $tr.next(); + } - while ($tr.length && $tr.find('>td[colspan]:not([colspan="1"])').length) { - $tr = $tr.next(); - } + var trLength = $tr.find('> *').length; + $tr.find('> *').each(function (i, el) { + var $this = $__default['default'](el); - $tr.find('> *').each(function (i, el) { - var $this = $(el); - var index = i; + if (Utils.hasDetailViewIcon(_this14.options)) { + if (i === 0 && _this14.options.detailViewAlign !== 'right' || i === trLength - 1 && _this14.options.detailViewAlign === 'right') { + var $thDetail = $ths.filter('.detail'); - if (_this13.options.detailView && !_this13.options.cardView) { - if (i === 0) { - var $thDetail = $ths.filter('.detail'); - var _zoomWidth = $thDetail.width() - $thDetail.find('.fht-cell').width(); - $thDetail.find('.fht-cell').width($this.innerWidth() - _zoomWidth); - } - index = i - 1; - } + var _zoomWidth = $thDetail.innerWidth() - $thDetail.find('.fht-cell').width(); - if (index === -1) { + $thDetail.find('.fht-cell').width($this.innerWidth() - _zoomWidth); return; } + } - var $th = _this13.$header_.find(Utils.sprintf('th[data-field="%s"]', visibleFields[index])); - if ($th.length > 1) { - $th = $($ths[$this[0].cellIndex]); - } + var index = i - Utils.getDetailViewIndexOffset(_this14.options); - var zoomWidth = $th.width() - $th.find('.fht-cell').width(); - $th.find('.fht-cell').width($this.innerWidth() - zoomWidth); - }); + var $th = _this14.$header_.find(Utils.sprintf('th[data-field="%s"]', visibleFields[index])); - this.horizontalScroll(); - this.trigger('post-header'); + if ($th.length > 1) { + $th = $__default['default']($ths[$this[0].cellIndex]); + } + + var zoomWidth = $th.innerWidth() - $th.find('.fht-cell').width(); + $th.find('.fht-cell').width($this.innerWidth() - zoomWidth); + }); + this.horizontalScroll(); + this.trigger('post-header'); + } + }, { + key: "initFooter", + value: function initFooter() { + if (!this.options.showFooter || this.options.cardView) { + // do nothing + return; } - }, { - key: 'resetFooter', - value: function resetFooter() { - var data = this.getData(); - var html = []; - if (!this.options.showFooter || this.options.cardView) { - // do nothing - return; - } + var data = this.getData(); + var html = []; + var detailTemplate = ''; - if (!this.options.cardView && this.options.detailView) { - html.push('
    '); - } + if (Utils.hasDetailViewIcon(this.options)) { + detailTemplate = '
    '; + } - for (var _iterator17 = this.columns, _isArray17 = Array.isArray(_iterator17), _i19 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) { - var _ref37; + if (detailTemplate && this.options.detailViewAlign !== 'right') { + html.push(detailTemplate); + } - if (_isArray17) { - if (_i19 >= _iterator17.length) break; - _ref37 = _iterator17[_i19++]; - } else { - _i19 = _iterator17.next(); - if (_i19.done) break; - _ref37 = _i19.value; - } - - var column = _ref37; + var _iterator4 = _createForOfIteratorHelper(this.columns), + _step4; + try { + for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { + var column = _step4.value; var falign = ''; - var valign = ''; var csses = []; var style = {}; var class_ = Utils.sprintf(' class="%s"', column['class']); - if (!column.visible) { + if (!column.visible || this.footerData && this.footerData.length > 0 && !(column.field in this.footerData[0])) { continue; } @@ -2656,1112 +6117,1293 @@ falign = Utils.sprintf('text-align: %s; ', column.falign ? column.falign : column.align); valign = Utils.sprintf('vertical-align: %s; ', column.valign); - style = Utils.calculateObjectValue(null, this.options.footerStyle, [column]); if (style && style.css) { - for (var _iterator18 = function (target) { - return Object.keys(target).map(function (key) { - return [key, target[key]]; - }); - }(style.css), _isArray18 = Array.isArray(_iterator18), _i20 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) { - var _ref38; + for (var _i12 = 0, _Object$entries11 = Object.entries(style.css); _i12 < _Object$entries11.length; _i12++) { + var _Object$entries11$_i = _slicedToArray(_Object$entries11[_i12], 2), + key = _Object$entries11$_i[0], + _value3 = _Object$entries11$_i[1]; - if (_isArray18) { - if (_i20 >= _iterator18.length) break; - _ref38 = _iterator18[_i20++]; - } else { - _i20 = _iterator18.next(); - if (_i20.done) break; - _ref38 = _i20.value; - } - - var _ref39 = _ref38, - _ref40 = _slicedToArray(_ref39, 2), - _key5 = _ref40[0], - value = _ref40[1]; - - csses.push(_key5 + ': ' + value); + csses.push("".concat(key, ": ").concat(_value3)); } } + if (style && style.classes) { class_ = Utils.sprintf(' class="%s"', column['class'] ? [column['class'], style.classes].join(' ') : style.classes); } - html.push(''); + html.push(' 0) { + colspan = this.footerData[0]["_".concat(column.field, "_colspan")] || 0; + } + + if (colspan) { + html.push(" colspan=\"".concat(colspan, "\" ")); + } + + html.push('>'); html.push('
    '); + var value = ''; - html.push(Utils.calculateObjectValue(column, column.footerFormatter, [data], '')); + if (this.footerData && this.footerData.length > 0) { + value = this.footerData[0][column.field] || ''; + } + html.push(Utils.calculateObjectValue(column, column.footerFormatter, [data, value], value)); html.push('
    '); html.push('
    '); html.push('
    '); html.push(''); } - - this.$tableFooter.find('tr').html(html.join('')); - this.$tableFooter.show(); - this.fitFooter(); + } catch (err) { + _iterator4.e(err); + } finally { + _iterator4.f(); } - }, { - key: 'fitFooter', - value: function fitFooter() { - var _this14 = this; - if (this.$el.is(':hidden')) { - setTimeout(function () { - return _this14.fitFooter(); - }, 100); - return; - } + if (detailTemplate && this.options.detailViewAlign === 'right') { + html.push(detailTemplate); + } - var fixedBody = this.$tableBody.get(0); - var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? Utils.getScrollBarWidth() : 0; + if (!this.options.height && !this.$tableFooter.length) { + this.$el.append(''); + this.$tableFooter = this.$el.find('tfoot'); + } - this.$tableFooter.css('margin-right', scrollWidth).find('table').css('width', this.$el.outerWidth()).attr('class', this.$el.attr('class')); + if (!this.$tableFooter.find('tr').length) { + this.$tableFooter.html('
    '); + } - var visibleFields = this.getVisibleFields(); - var $ths = this.$tableFooter.find('th'); - var $tr = this.$body.find('>tr:first-child:not(.no-records-found)'); + this.$tableFooter.find('tr').html(html.join('')); + this.trigger('post-footer', this.$tableFooter); + } + }, { + key: "fitFooter", + value: function fitFooter() { + var _this15 = this; - while ($tr.length && $tr.find('>td[colspan]:not([colspan="1"])').length) { - $tr = $tr.next(); - } + if (this.$el.is(':hidden')) { + setTimeout(function () { + return _this15.fitFooter(); + }, 100); + return; + } - $tr.find('> *').each(function (i, el) { - var $this = $(el); - var index = i; + var fixedBody = this.$tableBody.get(0); + var scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? Utils.getScrollBarWidth() : 0; + this.$tableFooter.css('margin-right', scrollWidth).find('table').css('width', this.$el.outerWidth()).attr('class', this.$el.attr('class')); + var $ths = this.$tableFooter.find('th'); + var $tr = this.$body.find('>tr:first-child:not(.no-records-found)'); + $ths.find('.fht-cell').width('auto'); - if (_this14.options.detailView && !_this14.options.cardView) { - if (i === 0) { - var $thDetail = $ths.filter('.detail'); - var _zoomWidth2 = $thDetail.width() - $thDetail.find('.fht-cell').width(); - $thDetail.find('.fht-cell').width($this.innerWidth() - _zoomWidth2); - } - index = i - 1; - } + while ($tr.length && $tr.find('>td[colspan]:not([colspan="1"])').length) { + $tr = $tr.next(); + } - if (index === -1) { + var trLength = $tr.find('> *').length; + $tr.find('> *').each(function (i, el) { + var $this = $__default['default'](el); + + if (Utils.hasDetailViewIcon(_this15.options)) { + if (i === 0 && _this15.options.detailViewAlign === 'left' || i === trLength - 1 && _this15.options.detailViewAlign === 'right') { + var $thDetail = $ths.filter('.detail'); + + var _zoomWidth2 = $thDetail.innerWidth() - $thDetail.find('.fht-cell').width(); + + $thDetail.find('.fht-cell').width($this.innerWidth() - _zoomWidth2); return; } - - var $th = $ths.eq(i); - var zoomWidth = $th.width() - $th.find('.fht-cell').width(); - $th.find('.fht-cell').width($this.innerWidth() - zoomWidth); - }); - - this.horizontalScroll(); - } - }, { - key: 'horizontalScroll', - value: function horizontalScroll() { - var _this15 = this; - - // horizontal scroll event - // TODO: it's probably better improving the layout than binding to scroll event - - this.trigger('scroll-body'); - this.$tableBody.off('scroll').on('scroll', function (_ref41) { - var currentTarget = _ref41.currentTarget; - - if (_this15.options.showHeader && _this15.options.height) { - _this15.$tableHeader.scrollLeft($(currentTarget).scrollLeft()); - } - - if (_this15.options.showFooter && !_this15.options.cardView) { - _this15.$tableFooter.scrollLeft($(currentTarget).scrollLeft()); - } - }); - } - }, { - key: 'toggleColumn', - value: function toggleColumn(index, checked, needUpdate) { - if (index === -1) { - return; } - this.columns[index].visible = checked; - this.initHeader(); - this.initSearch(); - this.initPagination(); - this.initBody(); - if (this.options.showColumns) { - var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); + var $th = $ths.eq(i); + var zoomWidth = $th.innerWidth() - $th.find('.fht-cell').width(); + $th.find('.fht-cell').width($this.innerWidth() - zoomWidth); + }); + this.horizontalScroll(); + } + }, { + key: "horizontalScroll", + value: function horizontalScroll() { + var _this16 = this; - if (needUpdate) { - $items.filter(Utils.sprintf('[value="%s"]', index)).prop('checked', checked); - } + // horizontal scroll event + // TODO: it's probably better improving the layout than binding to scroll event + this.$tableBody.off('scroll').on('scroll', function () { + var scrollLeft = _this16.$tableBody.scrollLeft(); - if ($items.filter(':checked').length <= this.options.minimumCountColumns) { - $items.filter(':checked').prop('disabled', true); - } + if (_this16.options.showHeader && _this16.options.height) { + _this16.$tableHeader.scrollLeft(scrollLeft); } - } - }, { - key: 'getVisibleFields', - value: function getVisibleFields() { - var visibleFields = []; - for (var _iterator19 = this.header.fields, _isArray19 = Array.isArray(_iterator19), _i21 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) { - var _ref42; + if (_this16.options.showFooter && !_this16.options.cardView) { + _this16.$tableFooter.scrollLeft(scrollLeft); + } - if (_isArray19) { - if (_i21 >= _iterator19.length) break; - _ref42 = _iterator19[_i21++]; - } else { - _i21 = _iterator19.next(); - if (_i21.done) break; - _ref42 = _i21.value; - } + _this16.trigger('scroll-body', _this16.$tableBody); + }); + } + }, { + key: "getVisibleFields", + value: function getVisibleFields() { + var visibleFields = []; - var field = _ref42; + var _iterator5 = _createForOfIteratorHelper(this.header.fields), + _step5; + try { + for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) { + var field = _step5.value; var column = this.columns[this.fieldsColumnsIndex[field]]; - if (!column.visible) { + if (!column || !column.visible) { continue; } + visibleFields.push(field); } - return visibleFields; + } catch (err) { + _iterator5.e(err); + } finally { + _iterator5.f(); } - }, { - key: 'resetView', - value: function resetView(params) { - var padding = 0; - if (params && params.height) { - this.options.height = params.height; + return visibleFields; + } + }, { + key: "initHiddenRows", + value: function initHiddenRows() { + this.hiddenRows = []; + } // PUBLIC FUNCTION DEFINITION + // ======================= + + }, { + key: "getOptions", + value: function getOptions() { + // deep copy and remove data + var options = $__default['default'].extend({}, this.options); + delete options.data; + return $__default['default'].extend(true, {}, options); + } + }, { + key: "refreshOptions", + value: function refreshOptions(options) { + // If the objects are equivalent then avoid the call of destroy / init methods + if (Utils.compareObjects(this.options, options, true)) { + return; + } + + this.options = $__default['default'].extend(this.options, options); + this.trigger('refresh-options', this.options); + this.destroy(); + this.init(); + } + }, { + key: "getData", + value: function getData(params) { + var _this17 = this; + + var data = this.options.data; + + if ((this.searchText || this.options.customSearch || this.options.sortName !== undefined || this.enableCustomSort || // Fix #4616: this.enableCustomSort is for extensions + !Utils.isEmptyObject(this.filterColumns) || !Utils.isEmptyObject(this.filterColumnsPartial)) && (!params || !params.unfiltered)) { + data = this.data; + } + + if (params && params.useCurrentPage) { + data = data.slice(this.pageFrom - 1, this.pageTo); + } + + if (params && !params.includeHiddenRows) { + var hiddenRows = this.getHiddenRows(); + data = data.filter(function (row) { + return Utils.findIndex(hiddenRows, row) === -1; + }); + } + + if (params && params.formatted) { + data.forEach(function (row) { + for (var _i13 = 0, _Object$entries12 = Object.entries(row); _i13 < _Object$entries12.length; _i13++) { + var _Object$entries12$_i = _slicedToArray(_Object$entries12[_i13], 2), + key = _Object$entries12$_i[0], + value = _Object$entries12$_i[1]; + + var column = _this17.columns[_this17.fieldsColumnsIndex[key]]; + + if (!column) { + return; + } + + row[key] = Utils.calculateObjectValue(column, _this17.header.formatters[column.fieldIndex], [value, row, row.index, column.field], value); + } + }); + } + + return data; + } + }, { + key: "getSelections", + value: function getSelections() { + var _this18 = this; + + return (this.options.maintainMetaData ? this.options.data : this.data).filter(function (row) { + return row[_this18.header.stateField] === true; + }); + } + }, { + key: "load", + value: function load(_data) { + var fixedScroll = false; + var data = _data; // #431: support pagination + + if (this.options.pagination && this.options.sidePagination === 'server') { + this.options.totalRows = data[this.options.totalField]; + this.options.totalNotFiltered = data[this.options.totalNotFilteredField]; + this.footerData = data[this.options.footerField] ? [data[this.options.footerField]] : undefined; + } + + fixedScroll = data.fixedScroll; + data = Array.isArray(data) ? data : data[this.options.dataField]; + this.initData(data); + this.initSearch(); + this.initPagination(); + this.initBody(fixedScroll); + } + }, { + key: "append", + value: function append(data) { + this.initData(data, 'append'); + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "prepend", + value: function prepend(data) { + this.initData(data, 'prepend'); + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "remove", + value: function remove(params) { + var removed = 0; + + for (var i = this.options.data.length - 1; i >= 0; i--) { + var row = this.options.data[i]; + + if (!row.hasOwnProperty(params.field) && params.field !== '$index') { + continue; } - this.$selectAll.prop('checked', this.$selectItem.length > 0 && this.$selectItem.length === this.$selectItem.filter(':checked').length); - - if (this.options.cardView) { - // remove the element css - this.$el.css('margin-top', '0'); - this.$tableContainer.css('padding-bottom', '0'); - this.$tableFooter.hide(); - return; + if (!row.hasOwnProperty(params.field) && params.field === '$index' && params.values.includes(i) || params.values.includes(row[params.field])) { + removed++; + this.options.data.splice(i, 1); } + } - if (this.options.showHeader && this.options.height) { - this.$tableHeader.show(); - this.resetHeader(); - padding += this.$header.outerHeight(true); + if (!removed) { + return; + } + + if (this.options.sidePagination === 'server') { + this.options.totalRows -= removed; + this.data = _toConsumableArray(this.options.data); + } + + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "removeAll", + value: function removeAll() { + if (this.options.data.length > 0) { + this.options.data.splice(0, this.options.data.length); + this.initSearch(); + this.initPagination(); + this.initBody(true); + } + } + }, { + key: "insertRow", + value: function insertRow(params) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { + return; + } + + this.options.data.splice(params.index, 0, params.row); + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "updateRow", + value: function updateRow(params) { + var allParams = Array.isArray(params) ? params : [params]; + + var _iterator6 = _createForOfIteratorHelper(allParams), + _step6; + + try { + for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) { + var _params = _step6.value; + + if (!_params.hasOwnProperty('index') || !_params.hasOwnProperty('row')) { + continue; + } + + if (_params.hasOwnProperty('replace') && _params.replace) { + this.options.data[_params.index] = _params.row; + } else { + $__default['default'].extend(this.options.data[_params.index], _params.row); + } + } + } catch (err) { + _iterator6.e(err); + } finally { + _iterator6.f(); + } + + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "getRowByUniqueId", + value: function getRowByUniqueId(_id) { + var uniqueId = this.options.uniqueId; + var len = this.options.data.length; + var id = _id; + var dataRow = null; + var i; + var row; + var rowUniqueId; + + for (i = len - 1; i >= 0; i--) { + row = this.options.data[i]; + + if (row.hasOwnProperty(uniqueId)) { + // uniqueId is a column + rowUniqueId = row[uniqueId]; + } else if (row._data && row._data.hasOwnProperty(uniqueId)) { + // uniqueId is a row data property + rowUniqueId = row._data[uniqueId]; } else { - this.$tableHeader.hide(); - this.trigger('post-header'); + continue; } - if (this.options.showFooter) { - this.resetFooter(); - if (this.options.height) { - padding += this.$tableFooter.outerHeight(true); + if (typeof rowUniqueId === 'string') { + id = id.toString(); + } else if (typeof rowUniqueId === 'number') { + if (Number(rowUniqueId) === rowUniqueId && rowUniqueId % 1 === 0) { + id = parseInt(id); + } else if (rowUniqueId === Number(rowUniqueId) && rowUniqueId !== 0) { + id = parseFloat(id); } } - if (this.options.height) { - var toolbarHeight = this.$toolbar.outerHeight(true); - var paginationHeight = this.$pagination.outerHeight(true); - var height = this.options.height - toolbarHeight - paginationHeight; - var tableHeight = this.$tableBody.find('table').outerHeight(true); - this.$tableContainer.css('height', height + 'px'); - this.$tableBorder && this.$tableBorder.css('height', height - tableHeight - padding - 1 + 'px'); - } - - // Assign the correct sortable arrow - this.getCaret(); - this.$tableContainer.css('padding-bottom', padding + 'px'); - this.trigger('reset-view'); - } - }, { - key: 'getData', - value: function getData(useCurrentPage) { - var data = this.options.data; - if (this.searchText || this.options.sortName || !Utils.isEmptyObject(this.filterColumns) || !Utils.isEmptyObject(this.filterColumnsPartial)) { - data = this.data; - } - - if (useCurrentPage) { - return data.slice(this.pageFrom - 1, this.pageTo); - } - - return data; - } - }, { - key: 'load', - value: function load(_data) { - var fixedScroll = false; - var data = _data; - - // #431: support pagination - if (this.options.pagination && this.options.sidePagination === 'server') { - this.options.totalRows = data[this.options.totalField]; - } - - fixedScroll = data.fixedScroll; - data = Array.isArray(data) ? data : data[this.options.dataField]; - - this.initData(data); - this.initSearch(); - this.initPagination(); - this.initBody(fixedScroll); - } - }, { - key: 'append', - value: function append(data) { - this.initData(data, 'append'); - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); - } - }, { - key: 'prepend', - value: function prepend(data) { - this.initData(data, 'prepend'); - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); - } - }, { - key: 'remove', - value: function remove(params) { - var len = this.options.data.length; - var i = void 0; - var row = void 0; - - if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) { - return; - } - - for (i = len - 1; i >= 0; i--) { - row = this.options.data[i]; - - if (!row.hasOwnProperty(params.field)) { - continue; - } - if (params.values.indexOf(row[params.field]) !== -1) { - this.options.data.splice(i, 1); - if (this.options.sidePagination === 'server') { - this.options.totalRows -= 1; - } - } - } - - if (len === this.options.data.length) { - return; - } - - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); - } - }, { - key: 'removeAll', - value: function removeAll() { - if (this.options.data.length > 0) { - this.options.data.splice(0, this.options.data.length); - this.initSearch(); - this.initPagination(); - this.initBody(true); + if (rowUniqueId === id) { + dataRow = row; + break; } } - }, { - key: 'getRowByUniqueId', - value: function getRowByUniqueId(_id) { - var uniqueId = this.options.uniqueId; - var len = this.options.data.length; - var id = _id; - var dataRow = null; - var i = void 0; - var row = void 0; - var rowUniqueId = void 0; - for (i = len - 1; i >= 0; i--) { - row = this.options.data[i]; + return dataRow; + } + }, { + key: "updateByUniqueId", + value: function updateByUniqueId(params) { + var allParams = Array.isArray(params) ? params : [params]; - if (row.hasOwnProperty(uniqueId)) { - // uniqueId is a column - rowUniqueId = row[uniqueId]; - } else if (row._data && row._data.hasOwnProperty(uniqueId)) { - // uniqueId is a row data property - rowUniqueId = row._data[uniqueId]; - } else { + var _iterator7 = _createForOfIteratorHelper(allParams), + _step7; + + try { + for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) { + var _params2 = _step7.value; + + if (!_params2.hasOwnProperty('id') || !_params2.hasOwnProperty('row')) { continue; } - if (typeof rowUniqueId === 'string') { - id = id.toString(); - } else if (typeof rowUniqueId === 'number') { - if (Number(rowUniqueId) === rowUniqueId && rowUniqueId % 1 === 0) { - id = parseInt(id); - } else if (rowUniqueId === Number(rowUniqueId) && rowUniqueId !== 0) { - id = parseFloat(id); - } - } - - if (rowUniqueId === id) { - dataRow = row; - break; - } - } - - return dataRow; - } - }, { - key: 'removeByUniqueId', - value: function removeByUniqueId(id) { - var len = this.options.data.length; - var row = this.getRowByUniqueId(id); - - if (row) { - this.options.data.splice(this.options.data.indexOf(row), 1); - } - - if (len === this.options.data.length) { - return; - } - - this.initSearch(); - this.initPagination(); - this.initBody(true); - } - }, { - key: 'updateByUniqueId', - value: function updateByUniqueId(params) { - var allParams = Array.isArray(params) ? params : [params]; - - for (var _iterator20 = allParams, _isArray20 = Array.isArray(_iterator20), _i22 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) { - var _ref43; - - if (_isArray20) { - if (_i22 >= _iterator20.length) break; - _ref43 = _iterator20[_i22++]; - } else { - _i22 = _iterator20.next(); - if (_i22.done) break; - _ref43 = _i22.value; - } - - var _params = _ref43; - - if (!_params.hasOwnProperty('id') || !_params.hasOwnProperty('row')) { - continue; - } - - var rowId = this.options.data.indexOf(this.getRowByUniqueId(_params.id)); + var rowId = this.options.data.indexOf(this.getRowByUniqueId(_params2.id)); if (rowId === -1) { continue; } - $.extend(this.options.data[rowId], _params.row); - } - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); + if (_params2.hasOwnProperty('replace') && _params2.replace) { + this.options.data[rowId] = _params2.row; + } else { + $__default['default'].extend(this.options.data[rowId], _params2.row); + } + } + } catch (err) { + _iterator7.e(err); + } finally { + _iterator7.f(); } - }, { - key: 'refreshColumnTitle', - value: function refreshColumnTitle(params) { - if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) { + + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + } + }, { + key: "removeByUniqueId", + value: function removeByUniqueId(id) { + var len = this.options.data.length; + var row = this.getRowByUniqueId(id); + + if (row) { + this.options.data.splice(this.options.data.indexOf(row), 1); + } + + if (len === this.options.data.length) { + return; + } + + if (this.options.sidePagination === 'server') { + this.options.totalRows -= 1; + this.data = _toConsumableArray(this.options.data); + } + + this.initSearch(); + this.initPagination(); + this.initBody(true); + } + }, { + key: "updateCell", + value: function updateCell(params) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('field') || !params.hasOwnProperty('value')) { + return; + } + + this.data[params.index][params.field] = params.value; + + if (params.reinit === false) { + return; + } + + this.initSort(); + this.initBody(true); + } + }, { + key: "updateCellByUniqueId", + value: function updateCellByUniqueId(params) { + var _this19 = this; + + var allParams = Array.isArray(params) ? params : [params]; + allParams.forEach(function (_ref6) { + var id = _ref6.id, + field = _ref6.field, + value = _ref6.value; + + var rowId = _this19.options.data.indexOf(_this19.getRowByUniqueId(id)); + + if (rowId === -1) { return; } - this.columns[this.fieldsColumnsIndex[params.field]].title = this.options.escape ? Utils.escapeHTML(params.title) : params.title; + _this19.options.data[rowId][field] = value; + }); - if (this.columns[this.fieldsColumnsIndex[params.field]].visible) { - var header = this.options.height !== undefined ? this.$tableHeader : this.$header; - header.find('th[data-field]').each(function (i, el) { - if ($(el).data('field') === params.field) { - $($(el).find('.th-inner')[0]).text(params.title); - return false; + if (params.reinit === false) { + return; + } + + this.initSort(); + this.initBody(true); + } + }, { + key: "showRow", + value: function showRow(params) { + this._toggleRow(params, true); + } + }, { + key: "hideRow", + value: function hideRow(params) { + this._toggleRow(params, false); + } + }, { + key: "_toggleRow", + value: function _toggleRow(params, visible) { + var row; + + if (params.hasOwnProperty('index')) { + row = this.getData()[params.index]; + } else if (params.hasOwnProperty('uniqueId')) { + row = this.getRowByUniqueId(params.uniqueId); + } + + if (!row) { + return; + } + + var index = Utils.findIndex(this.hiddenRows, row); + + if (!visible && index === -1) { + this.hiddenRows.push(row); + } else if (visible && index > -1) { + this.hiddenRows.splice(index, 1); + } + + this.initBody(true); + this.initPagination(); + } + }, { + key: "getHiddenRows", + value: function getHiddenRows(show) { + if (show) { + this.initHiddenRows(); + this.initBody(true); + this.initPagination(); + return; + } + + var data = this.getData(); + var rows = []; + + var _iterator8 = _createForOfIteratorHelper(data), + _step8; + + try { + for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) { + var row = _step8.value; + + if (this.hiddenRows.includes(row)) { + rows.push(row); + } + } + } catch (err) { + _iterator8.e(err); + } finally { + _iterator8.f(); + } + + this.hiddenRows = rows; + return rows; + } + }, { + key: "showColumn", + value: function showColumn(field) { + var _this20 = this; + + var fields = Array.isArray(field) ? field : [field]; + fields.forEach(function (field) { + _this20._toggleColumn(_this20.fieldsColumnsIndex[field], true, true); + }); + } + }, { + key: "hideColumn", + value: function hideColumn(field) { + var _this21 = this; + + var fields = Array.isArray(field) ? field : [field]; + fields.forEach(function (field) { + _this21._toggleColumn(_this21.fieldsColumnsIndex[field], false, true); + }); + } + }, { + key: "_toggleColumn", + value: function _toggleColumn(index, checked, needUpdate) { + if (index === -1 || this.columns[index].visible === checked) { + return; + } + + this.columns[index].visible = checked; + this.initHeader(); + this.initSearch(); + this.initPagination(); + this.initBody(); + + if (this.options.showColumns) { + var $items = this.$toolbar.find('.keep-open input:not(".toggle-all")').prop('disabled', false); + + if (needUpdate) { + $items.filter(Utils.sprintf('[value="%s"]', index)).prop('checked', checked); + } + + if ($items.filter(':checked').length <= this.options.minimumCountColumns) { + $items.filter(':checked').prop('disabled', true); + } + } + } + }, { + key: "getVisibleColumns", + value: function getVisibleColumns() { + var _this22 = this; + + return this.columns.filter(function (column) { + return column.visible && !_this22.isSelectionColumn(column); + }); + } + }, { + key: "getHiddenColumns", + value: function getHiddenColumns() { + return this.columns.filter(function (_ref7) { + var visible = _ref7.visible; + return !visible; + }); + } + }, { + key: "isSelectionColumn", + value: function isSelectionColumn(column) { + return column.radio || column.checkbox; + } + }, { + key: "showAllColumns", + value: function showAllColumns() { + this._toggleAllColumns(true); + } + }, { + key: "hideAllColumns", + value: function hideAllColumns() { + this._toggleAllColumns(false); + } + }, { + key: "_toggleAllColumns", + value: function _toggleAllColumns(visible) { + var _this23 = this; + + var _iterator9 = _createForOfIteratorHelper(this.columns.slice().reverse()), + _step9; + + try { + for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) { + var column = _step9.value; + + if (column.switchable) { + if (!visible && this.options.showColumns && this.getVisibleColumns().length === this.options.minimumCountColumns) { + continue; + } + + column.visible = visible; + } + } + } catch (err) { + _iterator9.e(err); + } finally { + _iterator9.f(); + } + + this.initHeader(); + this.initSearch(); + this.initPagination(); + this.initBody(); + + if (this.options.showColumns) { + var $items = this.$toolbar.find('.keep-open input[type="checkbox"]:not(".toggle-all")').prop('disabled', false); + + if (visible) { + $items.prop('checked', visible); + } else { + $items.get().reverse().forEach(function (item) { + if ($items.filter(':checked').length > _this23.options.minimumCountColumns) { + $__default['default'](item).prop('checked', visible); } }); } - } - }, { - key: 'insertRow', - value: function insertRow(params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { - return; + + if ($items.filter(':checked').length <= this.options.minimumCountColumns) { + $items.filter(':checked').prop('disabled', true); } - this.options.data.splice(params.index, 0, params.row); - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); } - }, { - key: 'updateRow', - value: function updateRow(params) { - var allParams = Array.isArray(params) ? params : [params]; + } + }, { + key: "mergeCells", + value: function mergeCells(options) { + var row = options.index; + var col = this.getVisibleFields().indexOf(options.field); + var rowspan = options.rowspan || 1; + var colspan = options.colspan || 1; + var i; + var j; + var $tr = this.$body.find('>tr'); + col += Utils.getDetailViewIndexOffset(this.options); + var $td = $tr.eq(row).find('>td').eq(col); - for (var _iterator21 = allParams, _isArray21 = Array.isArray(_iterator21), _i23 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) { - var _ref44; + if (row < 0 || col < 0 || row >= this.data.length) { + return; + } - if (_isArray21) { - if (_i23 >= _iterator21.length) break; - _ref44 = _iterator21[_i23++]; - } else { - _i23 = _iterator21.next(); - if (_i23.done) break; - _ref44 = _i23.value; - } - - var _params2 = _ref44; - - if (!_params2.hasOwnProperty('index') || !_params2.hasOwnProperty('row')) { - continue; - } - $.extend(this.options.data[_params2.index], _params2.row); + for (i = row; i < row + rowspan; i++) { + for (j = col; j < col + colspan; j++) { + $tr.eq(i).find('>td').eq(j).hide(); } - - this.initSearch(); - this.initPagination(); - this.initSort(); - this.initBody(true); } - }, { - key: 'initHiddenRows', - value: function initHiddenRows() { - this.hiddenRows = []; + + $td.attr('rowspan', rowspan).attr('colspan', colspan).show(); + } + }, { + key: "checkAll", + value: function checkAll() { + this._toggleCheckAll(true); + } + }, { + key: "uncheckAll", + value: function uncheckAll() { + this._toggleCheckAll(false); + } + }, { + key: "_toggleCheckAll", + value: function _toggleCheckAll(checked) { + var rowsBefore = this.getSelections(); + this.$selectAll.add(this.$selectAll_).prop('checked', checked); + this.$selectItem.filter(':enabled').prop('checked', checked); + this.updateRows(); + this.updateSelected(); + var rowsAfter = this.getSelections(); + + if (checked) { + this.trigger('check-all', rowsAfter, rowsBefore); + return; } - }, { - key: 'showRow', - value: function showRow(params) { - this.toggleRow(params, true); - } - }, { - key: 'hideRow', - value: function hideRow(params) { - this.toggleRow(params, false); - } - }, { - key: 'toggleRow', - value: function toggleRow(params, visible) { - var row = void 0; - if (params.hasOwnProperty('index')) { - row = this.getData()[params.index]; - } else if (params.hasOwnProperty('uniqueId')) { - row = this.getRowByUniqueId(params.uniqueId); - } + this.trigger('uncheck-all', rowsAfter, rowsBefore); + } + }, { + key: "checkInvert", + value: function checkInvert() { + var $items = this.$selectItem.filter(':enabled'); + var checked = $items.filter(':checked'); + $items.each(function (i, el) { + $__default['default'](el).prop('checked', !$__default['default'](el).prop('checked')); + }); + this.updateRows(); + this.updateSelected(); + this.trigger('uncheck-some', checked); + checked = this.getSelections(); + this.trigger('check-some', checked); + } + }, { + key: "check", + value: function check(index) { + this._toggleCheck(true, index); + } + }, { + key: "uncheck", + value: function uncheck(index) { + this._toggleCheck(false, index); + } + }, { + key: "_toggleCheck", + value: function _toggleCheck(checked, index) { + var $el = this.$selectItem.filter("[data-index=\"".concat(index, "\"]")); + var row = this.data[index]; - if (!row) { - return; - } - - var index = Utils.findIndex(this.hiddenRows, row); - - if (!visible && index === -1) { - this.hiddenRows.push(row); - } else if (visible && index > -1) { - this.hiddenRows.splice(index, 1); - } - this.initBody(true); - } - }, { - key: 'getHiddenRows', - value: function getHiddenRows(show) { - if (show) { - this.initHiddenRows(); - this.initBody(true); - return; - } - var data = this.getData(); - var rows = []; - - for (var _iterator22 = data, _isArray22 = Array.isArray(_iterator22), _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) { - var _ref45; - - if (_isArray22) { - if (_i24 >= _iterator22.length) break; - _ref45 = _iterator22[_i24++]; - } else { - _i24 = _iterator22.next(); - if (_i24.done) break; - _ref45 = _i24.value; - } - - var row = _ref45; - - if (this.hiddenRows.indexOf(row) !== -1) { - rows.push(row); - } - } - this.hiddenRows = rows; - return rows; - } - }, { - key: 'mergeCells', - value: function mergeCells(options) { - var row = options.index; - var col = this.getVisibleFields().indexOf(options.field); - var rowspan = options.rowspan || 1; - var colspan = options.colspan || 1; - var i = void 0; - var j = void 0; - var $tr = this.$body.find('>tr'); - - if (this.options.detailView && !this.options.cardView) { - col += 1; - } - - var $td = $tr.eq(row).find('>td').eq(col); - - if (row < 0 || col < 0 || row >= this.data.length) { - return; - } - - for (i = row; i < row + rowspan; i++) { - for (j = col; j < col + colspan; j++) { - $tr.eq(i).find('>td').eq(j).hide(); - } - } - - $td.attr('rowspan', rowspan).attr('colspan', colspan).show(); - } - }, { - key: 'updateCell', - value: function updateCell(params) { - if (!params.hasOwnProperty('index') || !params.hasOwnProperty('field') || !params.hasOwnProperty('value')) { - return; - } - this.data[params.index][params.field] = params.value; - - if (params.reinit === false) { - return; - } - this.initSort(); - this.initBody(true); - } - }, { - key: 'updateCellById', - value: function updateCellById(params) { - var _this16 = this; - - if (!params.hasOwnProperty('id') || !params.hasOwnProperty('field') || !params.hasOwnProperty('value')) { - return; - } - var allParams = Array.isArray(params) ? params : [params]; - - allParams.forEach(function (_ref46) { - var id = _ref46.id, - field = _ref46.field, - value = _ref46.value; - - var rowId = _this16.options.data.indexOf(_this16.getRowByUniqueId(id)); - - if (rowId === -1) { - return; - } - _this16.data[rowId][field] = value; - }); - - if (params.reinit === false) { - return; - } - this.initSort(); - this.initBody(true); - } - }, { - key: 'getOptions', - value: function getOptions() { - return this.options; - } - }, { - key: 'getSelections', - value: function getSelections() { - var _this17 = this; - - // fix #2424: from html with checkbox - return this.options.data.filter(function (row) { - return row[_this17.header.stateField] === true; - }); - } - }, { - key: 'getAllSelections', - value: function getAllSelections() { - var _this18 = this; - - return this.options.data.filter(function (row) { - return row[_this18.header.stateField]; - }); - } - }, { - key: 'checkAll', - value: function checkAll() { - this.checkAll_(true); - } - }, { - key: 'uncheckAll', - value: function uncheckAll() { - this.checkAll_(false); - } - }, { - key: 'checkInvert', - value: function checkInvert() { - var $items = this.$selectItem.filter(':enabled'); - var checked = $items.filter(':checked'); - $items.each(function (i, el) { - $(el).prop('checked', !$(el).prop('checked')); - }); - this.updateRows(); - this.updateSelected(); - this.trigger('uncheck-some', checked); - checked = this.getSelections(); - this.trigger('check-some', checked); - } - }, { - key: 'checkAll_', - value: function checkAll_(checked) { - var rows = void 0; - if (!checked) { - rows = this.getSelections(); - } - this.$selectAll.add(this.$selectAll_).prop('checked', checked); - this.$selectItem.filter(':enabled').prop('checked', checked); - this.updateRows(); - if (checked) { - rows = this.getSelections(); - } - this.trigger(checked ? 'check-all' : 'uncheck-all', rows); - } - }, { - key: 'check', - value: function check(index) { - this.check_(true, index); - } - }, { - key: 'uncheck', - value: function uncheck(index) { - this.check_(false, index); - } - }, { - key: 'check_', - value: function check_(checked, index) { - var $el = this.$selectItem.filter('[data-index="' + index + '"]'); - var row = this.data[index]; - - if ($el.is(':radio') || this.options.singleSelect) { - for (var _iterator23 = this.options.data, _isArray23 = Array.isArray(_iterator23), _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) { - var _ref47; - - if (_isArray23) { - if (_i25 >= _iterator23.length) break; - _ref47 = _iterator23[_i25++]; - } else { - _i25 = _iterator23.next(); - if (_i25.done) break; - _ref47 = _i25.value; - } - - var r = _ref47; + if ($el.is(':radio') || this.options.singleSelect || this.options.multipleSelectRow && !this.multipleSelectRowCtrlKey && !this.multipleSelectRowShiftKey) { + var _iterator10 = _createForOfIteratorHelper(this.options.data), + _step10; + try { + for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) { + var r = _step10.value; r[this.header.stateField] = false; } - this.$selectItem.filter(':checked').not($el).prop('checked', false); + } catch (err) { + _iterator10.e(err); + } finally { + _iterator10.f(); } - row[this.header.stateField] = checked; - $el.prop('checked', checked); - this.updateSelected(); - this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el); + this.$selectItem.filter(':checked').not($el).prop('checked', false); } - }, { - key: 'checkBy', - value: function checkBy(obj) { - this.checkBy_(true, obj); - } - }, { - key: 'uncheckBy', - value: function uncheckBy(obj) { - this.checkBy_(false, obj); - } - }, { - key: 'checkBy_', - value: function checkBy_(checked, obj) { - var _this19 = this; - if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { - return; + row[this.header.stateField] = checked; + + if (this.options.multipleSelectRow) { + if (this.multipleSelectRowShiftKey && this.multipleSelectRowLastSelectedIndex >= 0) { + var _ref8 = this.multipleSelectRowLastSelectedIndex < index ? [this.multipleSelectRowLastSelectedIndex, index] : [index, this.multipleSelectRowLastSelectedIndex], + _ref9 = _slicedToArray(_ref8, 2), + fromIndex = _ref9[0], + toIndex = _ref9[1]; + + for (var i = fromIndex + 1; i < toIndex; i++) { + this.data[i][this.header.stateField] = true; + this.$selectItem.filter("[data-index=\"".concat(i, "\"]")).prop('checked', true); + } } - var rows = []; - this.options.data.forEach(function (row, i) { - if (!row.hasOwnProperty(obj.field)) { + this.multipleSelectRowCtrlKey = false; + this.multipleSelectRowShiftKey = false; + this.multipleSelectRowLastSelectedIndex = checked ? index : -1; + } + + $el.prop('checked', checked); + this.updateSelected(); + this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el); + } + }, { + key: "checkBy", + value: function checkBy(obj) { + this._toggleCheckBy(true, obj); + } + }, { + key: "uncheckBy", + value: function uncheckBy(obj) { + this._toggleCheckBy(false, obj); + } + }, { + key: "_toggleCheckBy", + value: function _toggleCheckBy(checked, obj) { + var _this24 = this; + + if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { + return; + } + + var rows = []; + this.data.forEach(function (row, i) { + if (!row.hasOwnProperty(obj.field)) { + return false; + } + + if (obj.values.includes(row[obj.field])) { + var $el = _this24.$selectItem.filter(':enabled').filter(Utils.sprintf('[data-index="%s"]', i)); + + $el = checked ? $el.not(':checked') : $el.filter(':checked'); + + if (!$el.length) { + return; + } + + $el.prop('checked', checked); + row[_this24.header.stateField] = checked; + rows.push(row); + + _this24.trigger(checked ? 'check' : 'uncheck', row, $el); + } + }); + this.updateSelected(); + this.trigger(checked ? 'check-some' : 'uncheck-some', rows); + } + }, { + key: "refresh", + value: function refresh(params) { + if (params && params.url) { + this.options.url = params.url; + } + + if (params && params.pageNumber) { + this.options.pageNumber = params.pageNumber; + } + + if (params && params.pageSize) { + this.options.pageSize = params.pageSize; + } + + this.trigger('refresh', this.initServer(params && params.silent, params && params.query, params && params.url)); + } + }, { + key: "destroy", + value: function destroy() { + this.$el.insertBefore(this.$container); + $__default['default'](this.options.toolbar).insertBefore(this.$el); + this.$container.next().remove(); + this.$container.remove(); + this.$el.html(this.$el_.html()).css('margin-top', '0').attr('class', this.$el_.attr('class') || ''); // reset the class + } + }, { + key: "resetView", + value: function resetView(params) { + var padding = 0; + + if (params && params.height) { + this.options.height = params.height; + } + + this.$selectAll.prop('checked', this.$selectItem.length > 0 && this.$selectItem.length === this.$selectItem.filter(':checked').length); + this.$tableContainer.toggleClass('has-card-view', this.options.cardView); + + if (!this.options.cardView && this.options.showHeader && this.options.height) { + this.$tableHeader.show(); + this.resetHeader(); + padding += this.$header.outerHeight(true) + 1; + } else { + this.$tableHeader.hide(); + this.trigger('post-header'); + } + + if (!this.options.cardView && this.options.showFooter) { + this.$tableFooter.show(); + this.fitFooter(); + + if (this.options.height) { + padding += this.$tableFooter.outerHeight(true); + } + } + + if (this.$container.hasClass('fullscreen')) { + this.$tableContainer.css('height', ''); + this.$tableContainer.css('width', ''); + } else if (this.options.height) { + if (this.$tableBorder) { + this.$tableBorder.css('width', ''); + this.$tableBorder.css('height', ''); + } + + var toolbarHeight = this.$toolbar.outerHeight(true); + var paginationHeight = this.$pagination.outerHeight(true); + var height = this.options.height - toolbarHeight - paginationHeight; + var $bodyTable = this.$tableBody.find('>table'); + var tableHeight = $bodyTable.outerHeight(); + this.$tableContainer.css('height', "".concat(height, "px")); + + if (this.$tableBorder && $bodyTable.is(':visible')) { + var tableBorderHeight = height - tableHeight - 2; + + if (this.$tableBody[0].scrollWidth - this.$tableBody.innerWidth()) { + tableBorderHeight -= Utils.getScrollBarWidth(); + } + + this.$tableBorder.css('width', "".concat($bodyTable.outerWidth(), "px")); + this.$tableBorder.css('height', "".concat(tableBorderHeight, "px")); + } + } + + if (this.options.cardView) { + // remove the element css + this.$el.css('margin-top', '0'); + this.$tableContainer.css('padding-bottom', '0'); + this.$tableFooter.hide(); + } else { + // Assign the correct sortable arrow + this.getCaret(); + this.$tableContainer.css('padding-bottom', "".concat(padding, "px")); + } + + this.trigger('reset-view'); + } + }, { + key: "showLoading", + value: function showLoading() { + this.$tableLoading.toggleClass('open', true); + var fontSize = this.options.loadingFontSize; + + if (this.options.loadingFontSize === 'auto') { + fontSize = this.$tableLoading.width() * 0.04; + fontSize = Math.max(12, fontSize); + fontSize = Math.min(32, fontSize); + fontSize = "".concat(fontSize, "px"); + } + + this.$tableLoading.find('.loading-text').css('font-size', fontSize); + } + }, { + key: "hideLoading", + value: function hideLoading() { + this.$tableLoading.toggleClass('open', false); + } + }, { + key: "togglePagination", + value: function togglePagination() { + this.options.pagination = !this.options.pagination; + var icon = this.options.showButtonIcons ? this.options.pagination ? this.options.icons.paginationSwitchDown : this.options.icons.paginationSwitchUp : ''; + var text = this.options.showButtonText ? this.options.pagination ? this.options.formatPaginationSwitchUp() : this.options.formatPaginationSwitchDown() : ''; + this.$toolbar.find('button[name="paginationSwitch"]').html("".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), " ").concat(text)); + this.updatePagination(); + } + }, { + key: "toggleFullscreen", + value: function toggleFullscreen() { + this.$el.closest('.bootstrap-table').toggleClass('fullscreen'); + this.resetView(); + } + }, { + key: "toggleView", + value: function toggleView() { + this.options.cardView = !this.options.cardView; + this.initHeader(); + var icon = this.options.showButtonIcons ? this.options.cardView ? this.options.icons.toggleOn : this.options.icons.toggleOff : ''; + var text = this.options.showButtonText ? this.options.cardView ? this.options.formatToggleOff() : this.options.formatToggleOn() : ''; + this.$toolbar.find('button[name="toggle"]').html("".concat(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon), " ").concat(text)); + this.initBody(); + this.trigger('toggle', this.options.cardView); + } + }, { + key: "resetSearch", + value: function resetSearch(text) { + var $search = Utils.getSearchInput(this); + $search.val(text || ''); + this.onSearch({ + currentTarget: $search + }); + } + }, { + key: "filterBy", + value: function filterBy(columns, options) { + this.filterOptions = Utils.isEmptyObject(options) ? this.options.filterOptions : $__default['default'].extend(this.options.filterOptions, options); + this.filterColumns = Utils.isEmptyObject(columns) ? {} : columns; + this.options.pageNumber = 1; + this.initSearch(); + this.updatePagination(); + } + }, { + key: "scrollTo", + value: function scrollTo(params) { + var options = { + unit: 'px', + value: 0 + }; + + if (_typeof(params) === 'object') { + options = Object.assign(options, params); + } else if (typeof params === 'string' && params === 'bottom') { + options.value = this.$tableBody[0].scrollHeight; + } else if (typeof params === 'string' || typeof params === 'number') { + options.value = params; + } + + var scrollTo = options.value; + + if (options.unit === 'rows') { + scrollTo = 0; + this.$body.find("> tr:lt(".concat(options.value, ")")).each(function (i, el) { + scrollTo += $__default['default'](el).outerHeight(true); + }); + } + + this.$tableBody.scrollTop(scrollTo); + } + }, { + key: "getScrollPosition", + value: function getScrollPosition() { + return this.$tableBody.scrollTop(); + } + }, { + key: "selectPage", + value: function selectPage(page) { + if (page > 0 && page <= this.options.totalPages) { + this.options.pageNumber = page; + this.updatePagination(); + } + } + }, { + key: "prevPage", + value: function prevPage() { + if (this.options.pageNumber > 1) { + this.options.pageNumber--; + this.updatePagination(); + } + } + }, { + key: "nextPage", + value: function nextPage() { + if (this.options.pageNumber < this.options.totalPages) { + this.options.pageNumber++; + this.updatePagination(); + } + } + }, { + key: "toggleDetailView", + value: function toggleDetailView(index, _columnDetailFormatter) { + var $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"]', index)); + + if ($tr.next().is('tr.detail-view')) { + this.collapseRow(index); + } else { + this.expandRow(index, _columnDetailFormatter); + } + + this.resetView(); + } + }, { + key: "expandRow", + value: function expandRow(index, _columnDetailFormatter) { + var row = this.data[index]; + var $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"][data-has-detail-view]', index)); + + if ($tr.next().is('tr.detail-view')) { + return; + } + + if (this.options.detailViewIcon) { + $tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailClose)); + } + + $tr.after(Utils.sprintf('', $tr.children('td').length)); + var $element = $tr.next().find('td'); + var detailFormatter = _columnDetailFormatter || this.options.detailFormatter; + var content = Utils.calculateObjectValue(this.options, detailFormatter, [index, row, $element], ''); + + if ($element.length === 1) { + $element.append(content); + } + + this.trigger('expand-row', index, row, $element); + } + }, { + key: "expandRowByUniqueId", + value: function expandRowByUniqueId(uniqueId) { + var row = this.getRowByUniqueId(uniqueId); + + if (!row) { + return; + } + + this.expandRow(this.data.indexOf(row)); + } + }, { + key: "collapseRow", + value: function collapseRow(index) { + var row = this.data[index]; + var $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"][data-has-detail-view]', index)); + + if (!$tr.next().is('tr.detail-view')) { + return; + } + + if (this.options.detailViewIcon) { + $tr.find('a.detail-icon').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.detailOpen)); + } + + this.trigger('collapse-row', index, row, $tr.next()); + $tr.next().remove(); + } + }, { + key: "collapseRowByUniqueId", + value: function collapseRowByUniqueId(uniqueId) { + var row = this.getRowByUniqueId(uniqueId); + + if (!row) { + return; + } + + this.collapseRow(this.data.indexOf(row)); + } + }, { + key: "expandAllRows", + value: function expandAllRows() { + var trs = this.$body.find('> tr[data-index][data-has-detail-view]'); + + for (var i = 0; i < trs.length; i++) { + this.expandRow($__default['default'](trs[i]).data('index')); + } + } + }, { + key: "collapseAllRows", + value: function collapseAllRows() { + var trs = this.$body.find('> tr[data-index][data-has-detail-view]'); + + for (var i = 0; i < trs.length; i++) { + this.collapseRow($__default['default'](trs[i]).data('index')); + } + } + }, { + key: "updateColumnTitle", + value: function updateColumnTitle(params) { + if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) { + return; + } + + this.columns[this.fieldsColumnsIndex[params.field]].title = this.options.escape ? Utils.escapeHTML(params.title) : params.title; + + if (this.columns[this.fieldsColumnsIndex[params.field]].visible) { + this.$header.find('th[data-field]').each(function (i, el) { + if ($__default['default'](el).data('field') === params.field) { + $__default['default']($__default['default'](el).find('.th-inner')[0]).text(params.title); return false; } - if (obj.values.indexOf(row[obj.field]) !== -1) { - var $el = _this19.$selectItem.filter(':enabled').filter(Utils.sprintf('[data-index="%s"]', i)).prop('checked', checked); - row[_this19.header.stateField] = checked; - rows.push(row); - _this19.trigger(checked ? 'check' : 'uncheck', row, $el); - } }); - this.updateSelected(); - this.trigger(checked ? 'check-some' : 'uncheck-some', rows); - } - }, { - key: 'destroy', - value: function destroy() { - this.$el.insertBefore(this.$container); - $(this.options.toolbar).insertBefore(this.$el); - this.$container.next().remove(); - this.$container.remove(); - this.$el.html(this.$el_.html()).css('margin-top', '0').attr('class', this.$el_.attr('class') || ''); // reset the class - } - }, { - key: 'showLoading', - value: function showLoading() { - this.$tableLoading.css('display', 'flex'); - } - }, { - key: 'hideLoading', - value: function hideLoading() { - this.$tableLoading.css('display', 'none'); - } - }, { - key: 'togglePagination', - value: function togglePagination() { - this.options.pagination = !this.options.pagination; - this.$toolbar.find('button[name="paginationSwitch"]').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.pagination ? this.options.icons.paginationSwitchDown : this.options.icons.paginationSwitchUp)); - this.updatePagination(); - } - }, { - key: 'toggleFullscreen', - value: function toggleFullscreen() { - this.$el.closest('.bootstrap-table').toggleClass('fullscreen'); this.resetView(); } - }, { - key: 'refresh', - value: function refresh(params) { - if (params && params.url) { - this.options.url = params.url; - } - if (params && params.pageNumber) { - this.options.pageNumber = params.pageNumber; - } - if (params && params.pageSize) { - this.options.pageSize = params.pageSize; - } - this.trigger('refresh', this.initServer(params && params.silent, params && params.query, params && params.url)); - } - }, { - key: 'resetWidth', - value: function resetWidth() { - if (this.options.showHeader && this.options.height) { - this.fitHeader(); - } - if (this.options.showFooter && !this.options.cardView) { - this.fitFooter(); - } - } - }, { - key: 'showColumn', - value: function showColumn(field) { - this.toggleColumn(this.fieldsColumnsIndex[field], true, true); - } - }, { - key: 'hideColumn', - value: function hideColumn(field) { - this.toggleColumn(this.fieldsColumnsIndex[field], false, true); - } - }, { - key: 'getHiddenColumns', - value: function getHiddenColumns() { - return this.columns.filter(function (_ref48) { - var visible = _ref48.visible; - return !visible; - }); - } - }, { - key: 'getVisibleColumns', - value: function getVisibleColumns() { - return this.columns.filter(function (_ref49) { - var visible = _ref49.visible; - return visible; - }); - } - }, { - key: 'toggleAllColumns', - value: function toggleAllColumns(visible) { - for (var _iterator24 = this.columns, _isArray24 = Array.isArray(_iterator24), _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) { - var _ref50; - - if (_isArray24) { - if (_i26 >= _iterator24.length) break; - _ref50 = _iterator24[_i26++]; - } else { - _i26 = _iterator24.next(); - if (_i26.done) break; - _ref50 = _i26.value; - } - - var column = _ref50; - - column.visible = visible; - } - - this.initHeader(); - this.initSearch(); - this.initPagination(); - this.initBody(); - if (this.options.showColumns) { - var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); - - if ($items.filter(':checked').length <= this.options.minimumCountColumns) { - $items.filter(':checked').prop('disabled', true); - } - } - } - }, { - key: 'showAllColumns', - value: function showAllColumns() { - this.toggleAllColumns(true); - } - }, { - key: 'hideAllColumns', - value: function hideAllColumns() { - this.toggleAllColumns(false); - } - }, { - key: 'filterBy', - value: function filterBy(columns) { - this.filterColumns = Utils.isEmptyObject(columns) ? {} : columns; - this.options.pageNumber = 1; - this.initSearch(); - this.updatePagination(); - } - }, { - key: 'scrollTo', - value: function scrollTo(_value) { - if (typeof _value === 'undefined') { - return this.$tableBody.scrollTop(); - } - - var value = _value; - if (typeof _value === 'string' && _value === 'bottom') { - value = this.$tableBody[0].scrollHeight; - } - this.$tableBody.scrollTop(value); - } - }, { - key: 'getScrollPosition', - value: function getScrollPosition() { - return this.scrollTo(); - } - }, { - key: 'selectPage', - value: function selectPage(page) { - if (page > 0 && page <= this.options.totalPages) { - this.options.pageNumber = page; - this.updatePagination(); - } - } - }, { - key: 'prevPage', - value: function prevPage() { - if (this.options.pageNumber > 1) { - this.options.pageNumber--; - this.updatePagination(); - } - } - }, { - key: 'nextPage', - value: function nextPage() { - if (this.options.pageNumber < this.options.totalPages) { - this.options.pageNumber++; - this.updatePagination(); - } - } - }, { - key: 'toggleView', - value: function toggleView() { - this.options.cardView = !this.options.cardView; - this.initHeader(); - // Fixed remove toolbar when click cardView button. - // this.initToolbar(); - this.$toolbar.find('button[name="toggle"]').html(Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.cardView ? this.options.icons.toggleOn : this.options.icons.toggleOff)); - this.initBody(); - this.trigger('toggle', this.options.cardView); - } - }, { - key: 'refreshOptions', - value: function refreshOptions(options) { - // If the objects are equivalent then avoid the call of destroy / init methods - if (Utils.compareObjects(this.options, options, true)) { - return; - } - this.options = $.extend(this.options, options); - this.trigger('refresh-options', this.options); - this.destroy(); - this.init(); - } - }, { - key: 'resetSearch', - value: function resetSearch(text) { - var $search = this.$toolbar.find('.search input'); - $search.val(text || ''); - this.onSearch({ currentTarget: $search }); - } - }, { - key: 'expandRow_', - value: function expandRow_(expand, index) { - var $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"]', index)); - if ($tr.next().is('tr.detail-view') === !expand) { - $tr.find('> td > .detail-icon').click(); - } - } - }, { - key: 'expandRow', - value: function expandRow(index) { - this.expandRow_(true, index); - } - }, { - key: 'collapseRow', - value: function collapseRow(index) { - this.expandRow_(false, index); - } - }, { - key: 'expandAllRows', - value: function expandAllRows(isSubTable) { - var _this20 = this; - - if (isSubTable) { - var $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"]', 0)); - var detailIcon = null; - var executeInterval = false; - var idInterval = -1; - - if (!$tr.next().is('tr.detail-view')) { - $tr.find('> td > .detail-icon').click(); - executeInterval = true; - } else if (!$tr.next().next().is('tr.detail-view')) { - $tr.next().find('.detail-icon').click(); - executeInterval = true; - } - - if (executeInterval) { - try { - idInterval = setInterval(function () { - detailIcon = _this20.$body.find('tr.detail-view').last().find('.detail-icon'); - if (detailIcon.length > 0) { - detailIcon.click(); - } else { - clearInterval(idInterval); - } - }, 1); - } catch (ex) { - clearInterval(idInterval); - } - } - } else { - var trs = this.$body.children(); - for (var i = 0; i < trs.length; i++) { - this.expandRow_(true, $(trs[i]).data('index')); - } - } - } - }, { - key: 'collapseAllRows', - value: function collapseAllRows(isSubTable) { - if (isSubTable) { - this.expandRow_(false, 0); - } else { - var trs = this.$body.children(); - for (var i = 0; i < trs.length; i++) { - this.expandRow_(false, $(trs[i]).data('index')); - } - } - } - }, { - key: 'updateFormatText', - value: function updateFormatText(name, text) { - if (this.options[Utils.sprintf('format%s', name)]) { - if (typeof text === 'string') { - this.options[Utils.sprintf('format%s', name)] = function () { - return text; - }; - } else if (typeof text === 'function') { - this.options[Utils.sprintf('format%s', name)] = text; - } - } - this.initToolbar(); - this.initPagination(); - this.initBody(); - } - }]); - - return BootstrapTable; - }(); - - BootstrapTable.DEFAULTS = DEFAULTS; - BootstrapTable.LOCALES = LOCALES; - BootstrapTable.COLUMN_DEFAULTS = COLUMN_DEFAULTS; - BootstrapTable.EVENTS = EVENTS; - - // BOOTSTRAP TABLE PLUGIN DEFINITION - // ======================= - - var allowedMethods = ['getOptions', 'getSelections', 'getAllSelections', 'getData', 'load', 'append', 'prepend', 'remove', 'removeAll', 'insertRow', 'updateRow', 'updateCell', 'updateByUniqueId', 'removeByUniqueId', 'getRowByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', 'mergeCells', 'refreshColumnTitle', 'checkAll', 'uncheckAll', 'checkInvert', 'check', 'uncheck', 'checkBy', 'uncheckBy', 'refresh', 'resetView', 'resetWidth', 'destroy', 'showLoading', 'hideLoading', 'showColumn', 'hideColumn', 'getHiddenColumns', 'getVisibleColumns', 'showAllColumns', 'hideAllColumns', 'filterBy', 'scrollTo', 'getScrollPosition', 'selectPage', 'prevPage', 'nextPage', 'togglePagination', 'toggleView', 'refreshOptions', 'resetSearch', 'expandRow', 'collapseRow', 'expandAllRows', 'collapseAllRows', 'updateFormatText', 'updateCellById']; - - $.BootstrapTable = BootstrapTable; - $.fn.bootstrapTable = function (option) { - for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key6 = 1; _key6 < _len3; _key6++) { - args[_key6 - 1] = arguments[_key6]; } + }, { + key: "updateFormatText", + value: function updateFormatText(formatName, text) { + if (!/^format/.test(formatName) || !this.options[formatName]) { + return; + } - var value = void 0; + if (typeof text === 'string') { + this.options[formatName] = function () { + return text; + }; + } else if (typeof text === 'function') { + this.options[formatName] = text; + } - this.each(function (i, el) { - var data = $(el).data('bootstrap.table'); - var options = $.extend({}, BootstrapTable.DEFAULTS, $(el).data(), (typeof option === 'undefined' ? 'undefined' : _typeof(option)) === 'object' && option); + this.initToolbar(); + this.initPagination(); + this.initBody(); + } + }]); - if (typeof option === 'string') { - var _data2; + return BootstrapTable; + }(); - if (!(allowedMethods.indexOf(option) !== -1)) { - throw new Error('Unknown method: ' + option); - } + BootstrapTable.VERSION = Constants.VERSION; + BootstrapTable.DEFAULTS = Constants.DEFAULTS; + BootstrapTable.LOCALES = Constants.LOCALES; + BootstrapTable.COLUMN_DEFAULTS = Constants.COLUMN_DEFAULTS; + BootstrapTable.METHODS = Constants.METHODS; + BootstrapTable.EVENTS = Constants.EVENTS; // BOOTSTRAP TABLE PLUGIN DEFINITION + // ======================= - if (!data) { - return; - } + $__default['default'].BootstrapTable = BootstrapTable; - value = (_data2 = data)[option].apply(_data2, args); + $__default['default'].fn.bootstrapTable = function (option) { + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key5 = 1; _key5 < _len2; _key5++) { + args[_key5 - 1] = arguments[_key5]; + } - if (option === 'destroy') { - $(el).removeData('bootstrap.table'); - } + var value; + this.each(function (i, el) { + var data = $__default['default'](el).data('bootstrap.table'); + var options = $__default['default'].extend({}, BootstrapTable.DEFAULTS, $__default['default'](el).data(), _typeof(option) === 'object' && option); + + if (typeof option === 'string') { + var _data2; + + if (!Constants.METHODS.includes(option)) { + throw new Error("Unknown method: ".concat(option)); } if (!data) { - $(el).data('bootstrap.table', data = new $.BootstrapTable(el, options)); + return; } - }); - return typeof value === 'undefined' ? this : value; - }; + value = (_data2 = data)[option].apply(_data2, args); - $.fn.bootstrapTable.Constructor = BootstrapTable; - $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS; - $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; - $.fn.bootstrapTable.locales = BootstrapTable.LOCALES; - $.fn.bootstrapTable.methods = allowedMethods; - $.fn.bootstrapTable.utils = Utils; + if (option === 'destroy') { + $__default['default'](el).removeData('bootstrap.table'); + } + } - // BOOTSTRAP TABLE INIT - // ======================= - - $(function () { - $('[data-toggle="table"]').bootstrapTable(); + if (!data) { + data = new $__default['default'].BootstrapTable(el, options); + $__default['default'](el).data('bootstrap.table', data); + data.init(); + } }); - })(jQuery); -}); \ No newline at end of file + return typeof value === 'undefined' ? this : value; + }; + + $__default['default'].fn.bootstrapTable.Constructor = BootstrapTable; + $__default['default'].fn.bootstrapTable.theme = Constants.THEME; + $__default['default'].fn.bootstrapTable.VERSION = Constants.VERSION; + $__default['default'].fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS; + $__default['default'].fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; + $__default['default'].fn.bootstrapTable.events = BootstrapTable.EVENTS; + $__default['default'].fn.bootstrapTable.locales = BootstrapTable.LOCALES; + $__default['default'].fn.bootstrapTable.methods = BootstrapTable.METHODS; + $__default['default'].fn.bootstrapTable.utils = Utils; // BOOTSTRAP TABLE INIT + // ======================= + + $__default['default'](function () { + $__default['default']('[data-toggle="table"]').bootstrapTable(); + }); + + return BootstrapTable; + +}))); From 887adf35f4234a20298a4fd45c27d951b371f641 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 29 May 2021 23:59:27 +1000 Subject: [PATCH 250/300] Add simple tile grid view for part list --- InvenTree/templates/base.html | 4 +-- InvenTree/templates/js/part.js | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index 07b1a1d34b..3cc9b33619 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -124,14 +124,14 @@ - - + + diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index f28bef059e..52f54dfa36 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -278,6 +278,58 @@ function loadParametricPartTable(table, options={}) { } +function partGridTile(part) { + // Generate a "grid tile" view for a particular part + + // Rows for table view + var rows = ''; + + if (part.IPN) { + rows += `{% trans "IPN" %}${part.IPN}`; + } + + rows += `{% trans "Stock" %}${part.in_stock}`; + + if (part.on_order) { + rows += `{$ trans "On Order" %}${part.on_order}`; + } + + if (part.building) { + rows += `{% trans "Building" %}${part.building}`; + } + + var html = ` + +
    +
    +
    + + ${part.full_name} + + ${makePartIcons(part)} +
    + ${part.description} +
    +
    +
    +
    + +
    +
    + + ${rows} +
    +
    +
    +
    +
    +
    + `; + + return html; +} + + function loadPartTable(table, url, options={}) { /* Load part listing data into specified table. * @@ -289,6 +341,7 @@ function loadPartTable(table, url, options={}) { * query: extra query params for API request * buttons: If provided, link buttons to selection status of this table * disableFilters: If true, disable custom filters + * gridView: If true, display as grid rather than standard table */ // Ensure category detail is included @@ -452,6 +505,18 @@ function loadPartTable(table, url, options={}) { formatNoMatches: function() { return '{% trans "No parts found" %}'; }, columns: columns, showColumns: true, + showCustomView: true, + showCustomViewButton: true, + customView: function(data) { + + var html = ''; + + data.forEach(function(row) { + html += partGridTile(row); + }); + + return `
    ${html}
    `; + } }); if (options.buttons) { From ee95cf5c2179e893cd44936f2b0c821e6605c22b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 30 May 2021 00:10:46 +1000 Subject: [PATCH 251/300] Clicking on thumbnail shows modal image --- InvenTree/templates/js/modals.js | 1 + InvenTree/templates/js/part.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/InvenTree/templates/js/modals.js b/InvenTree/templates/js/modals.js index f447fdce72..c8ebd90eb4 100644 --- a/InvenTree/templates/js/modals.js +++ b/InvenTree/templates/js/modals.js @@ -978,6 +978,7 @@ function showModalImage(image_url) { // Set image content $('#modal-image').attr('src', image_url); + modal.hide(); modal.show(); modal.animate({ diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index 52f54dfa36..a5b6def921 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -288,7 +288,13 @@ function partGridTile(part) { rows += `{% trans "IPN" %}${part.IPN}`; } - rows += `{% trans "Stock" %}${part.in_stock}`; + var stock = `${part.in_stock}`; + + if (!part.in_stock) { + stock = `{% trans "No Stock" %}`; + } + + rows += `{% trans "Stock" %}${stock}`; if (part.on_order) { rows += `{$ trans "On Order" %}${part.on_order}`; @@ -313,7 +319,7 @@ function partGridTile(part) {
    - +
    From e846c744f4454c6fab3bde108aa4cd13e5371da5 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 30 May 2021 00:23:05 +1000 Subject: [PATCH 252/300] Buttons to toggle between list and grid views --- InvenTree/part/templates/part/category.html | 24 +++++++++++++++++++++ InvenTree/templates/js/part.js | 7 +++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 2e6ebb7fca..c6fa5e84d6 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -128,6 +128,13 @@
  • {% trans "Export Data" %}
  • + + +
    @@ -169,6 +176,22 @@ toggleId: '#category-menu-toggle', }); + $('#view-list').hide(); + + $('#view-list').click(function() { + $('#view-list').hide(); + $('#view-grid').show(); + + $('#part-table').bootstrapTable('toggleCustomView'); + }); + + $('#view-grid').click(function() { + $('#view-grid').hide(); + $('#view-list').show(); + + $('#part-table').bootstrapTable('toggleCustomView'); + }); + $("#cat-create").click(function() { launchModalForm( "{% url 'category-create' %}", @@ -273,6 +296,7 @@ }, buttons: ['#part-options'], checkbox: true, + gridView: true, }, ); diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index a5b6def921..5c2840b121 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -347,7 +347,6 @@ function loadPartTable(table, url, options={}) { * query: extra query params for API request * buttons: If provided, link buttons to selection status of this table * disableFilters: If true, disable custom filters - * gridView: If true, display as grid rather than standard table */ // Ensure category detail is included @@ -511,8 +510,8 @@ function loadPartTable(table, url, options={}) { formatNoMatches: function() { return '{% trans "No parts found" %}'; }, columns: columns, showColumns: true, - showCustomView: true, - showCustomViewButton: true, + showCustomView: false, + showCustomViewButton: false, customView: function(data) { var html = ''; @@ -524,7 +523,7 @@ function loadPartTable(table, url, options={}) { return `
    ${html}
    `; } }); - + if (options.buttons) { linkButtonsToSelection($(table), options.buttons); } From f1ca17286f2be2e6d0835097b32af44c288983e7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 30 May 2021 00:38:59 +1000 Subject: [PATCH 253/300] Save grid / list selection to local storage settings --- InvenTree/part/templates/part/category.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index c6fa5e84d6..44cbeac99f 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -176,13 +176,12 @@ toggleId: '#category-menu-toggle', }); - $('#view-list').hide(); - $('#view-list').click(function() { $('#view-list').hide(); $('#view-grid').show(); $('#part-table').bootstrapTable('toggleCustomView'); + inventreeSave('part-grid-view', ''); }); $('#view-grid').click(function() { @@ -190,6 +189,7 @@ $('#view-list').show(); $('#part-table').bootstrapTable('toggleCustomView'); + inventreeSave('part-grid-view', 1); }); $("#cat-create").click(function() { @@ -300,4 +300,11 @@ }, ); + if (inventreeLoad("part-grid-view")) { + $('#view-grid').hide(); + $('#part-table').bootstrapTable('toggleCustomView'); + } else { + $('#view-list').hide(); + } + {% endblock %} \ No newline at end of file From b10410ca1f9e43b8586d491579b180bf9081ac34 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 31 May 2021 12:47:07 +1000 Subject: [PATCH 254/300] Update bootstrap-table library Updated javascript / css to latest version --- .../bootstrap-table-en-US.min.js | 0 .../bootstrap-table.css | 267 +- .../bootstrap-table.js | 0 .../addrbar/bootstrap-table-addrbar.js | 1829 +++++++- .../addrbar/bootstrap-table-addrbar.min.js | 10 + .../bootstrap-table-auto-refresh.js | 1247 +++++- .../bootstrap-table-auto-refresh.min.js | 10 + .../cookie/bootstrap-table-cookie.js | 2733 ++++++++++-- .../cookie/bootstrap-table-cookie.min.js | 10 + .../copy-rows/bootstrap-table-copy-rows.js | 1285 +++++- .../bootstrap-table-copy-rows.min.js | 10 + .../bootstrap-table-custom-view.min.js | 10 + .../defer-url/bootstrap-table-defer-url.js | 885 +++- .../bootstrap-table-defer-url.min.js | 10 + .../editable/bootstrap-table-editable.js | 1997 ++++++++- .../editable/bootstrap-table-editable.min.js | 10 + .../export/bootstrap-table-export.js | 2375 +++++++++- .../export/bootstrap-table-export.min.js | 10 + .../bootstrap-table-filter-control.css | 8 +- .../bootstrap-table-filter-control.js | 3839 +++++++++++++---- .../bootstrap-table-filter-control.min.css | 10 + .../bootstrap-table-filter-control.min.js | 10 + .../extensions/filter-control/utils.js | 2434 +++++++++++ .../extensions/filter-control/utils.min.js | 10 + .../bootstrap-table-fixed-columns.css | 26 +- .../bootstrap-table-fixed-columns.js | 1707 +++++++- .../bootstrap-table-fixed-columns.min.css | 10 + .../bootstrap-table-fixed-columns.min.js | 10 + .../group-by-v2/bootstrap-table-group-by.css | 13 +- .../group-by-v2/bootstrap-table-group-by.js | 1774 +++++++- .../bootstrap-table-group-by.min.css | 10 + .../bootstrap-table-group-by.min.js | 10 + .../bootstrap-table-i18n-enhance.js | 180 +- .../bootstrap-table-i18n-enhance.min.js | 10 + .../key-events/bootstrap-table-key-events.js | 1532 ++++++- .../bootstrap-table-key-events.min.js | 10 + .../mobile/bootstrap-table-mobile.js | 1385 +++++- .../mobile/bootstrap-table-mobile.min.js | 10 + .../bootstrap-table-multiple-sort.js | 2074 +++++++-- .../bootstrap-table-multiple-sort.min.js | 10 + .../bootstrap-table-page-jump-to.css | 19 +- .../bootstrap-table-page-jump-to.js | 1163 ++++- .../bootstrap-table-page-jump-to.min.css | 10 + .../bootstrap-table-page-jump-to.min.js | 10 + .../pipeline/bootstrap-table-pipeline.js | 1478 +++++-- .../pipeline/bootstrap-table-pipeline.min.js | 10 + .../extensions/print/bootstrap-table-print.js | 1765 +++++++- .../print/bootstrap-table-print.min.js | 10 + .../bootstrap-table-reorder-columns.js | 1564 ++++++- .../bootstrap-table-reorder-columns.min.js | 10 + .../bootstrap-table-reorder-rows.css | 20 +- .../bootstrap-table-reorder-rows.js | 1092 ++++- .../bootstrap-table-reorder-rows.min.css | 10 + .../bootstrap-table-reorder-rows.min.js | 10 + .../resizable/bootstrap-table-resizable.js | 953 +++- .../bootstrap-table-resizable.min.js | 10 + .../bootstrap-table-sticky-header.css | 3 +- .../bootstrap-table-sticky-header.js | 1315 +++++- .../bootstrap-table-sticky-header.min.css | 10 + .../bootstrap-table-sticky-header.min.js | 10 + .../toolbar/bootstrap-table-toolbar.js | 2183 +++++++++- .../toolbar/bootstrap-table-toolbar.min.js | 10 + .../treegrid/bootstrap-table-treegrid.js | 1278 +++++- .../treegrid/bootstrap-table-treegrid.min.js | 10 + .../css/bootstrap-table-filter-control.css | 13 - .../static/css/bootstrap-table-group-by.css | 11 - .../bootstrap-table-filter-control.js | 3021 ------------- .../bootstrap/bootstrap-table-group-by.js | 269 -- InvenTree/templates/base.html | 14 +- .../templates/registration/logged_out.html | 1 - InvenTree/templates/registration/login.html | 1 - .../registration/password_reset_complete.html | 1 - .../registration/password_reset_confirm.html | 1 - .../registration/password_reset_done.html | 1 - .../registration/password_reset_form.html | 1 - 75 files changed, 36980 insertions(+), 7087 deletions(-) rename InvenTree/InvenTree/static/{script/bootstrap => bootstrap-table}/bootstrap-table-en-US.min.js (100%) rename InvenTree/InvenTree/static/{css => bootstrap-table}/bootstrap-table.css (81%) rename InvenTree/InvenTree/static/{script/bootstrap => bootstrap-table}/bootstrap-table.js (100%) create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/cookie/bootstrap-table-cookie.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/copy-rows/bootstrap-table-copy-rows.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/custom-view/bootstrap-table-custom-view.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/defer-url/bootstrap-table-defer-url.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/editable/bootstrap-table-editable.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/export/bootstrap-table-export.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/filter-control/utils.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/filter-control/utils.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/fixed-columns/bootstrap-table-fixed-columns.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/fixed-columns/bootstrap-table-fixed-columns.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/i18n-enhance/bootstrap-table-i18n-enhance.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/key-events/bootstrap-table-key-events.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/page-jump-to/bootstrap-table-page-jump-to.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/pipeline/bootstrap-table-pipeline.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/print/bootstrap-table-print.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/resizable/bootstrap-table-resizable.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/sticky-header/bootstrap-table-sticky-header.min.css create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/sticky-header/bootstrap-table-sticky-header.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/toolbar/bootstrap-table-toolbar.min.js create mode 100644 InvenTree/InvenTree/static/bootstrap-table/extensions/treegrid/bootstrap-table-treegrid.min.js delete mode 100644 InvenTree/InvenTree/static/css/bootstrap-table-filter-control.css delete mode 100644 InvenTree/InvenTree/static/css/bootstrap-table-group-by.css delete mode 100644 InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-filter-control.js delete mode 100644 InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-group-by.js diff --git a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js b/InvenTree/InvenTree/static/bootstrap-table/bootstrap-table-en-US.min.js similarity index 100% rename from InvenTree/InvenTree/static/script/bootstrap/bootstrap-table-en-US.min.js rename to InvenTree/InvenTree/static/bootstrap-table/bootstrap-table-en-US.min.js diff --git a/InvenTree/InvenTree/static/css/bootstrap-table.css b/InvenTree/InvenTree/static/bootstrap-table/bootstrap-table.css similarity index 81% rename from InvenTree/InvenTree/static/css/bootstrap-table.css rename to InvenTree/InvenTree/static/bootstrap-table/bootstrap-table.css index 7a71650329..5729f104bb 100644 --- a/InvenTree/InvenTree/static/css/bootstrap-table.css +++ b/InvenTree/InvenTree/static/bootstrap-table/bootstrap-table.css @@ -1,14 +1,14 @@ -@charset "UTF-8"; /** * @author zhixin wen - * version: 1.14.2 + * version: 1.18.3 * https://github.com/wenzhixin/bootstrap-table/ */ -.bootstrap-table .fixed-table-toolbar:after { +.bootstrap-table .fixed-table-toolbar::after { content: ""; display: block; clear: both; } + .bootstrap-table .fixed-table-toolbar .bs-bars, .bootstrap-table .fixed-table-toolbar .search, .bootstrap-table .fixed-table-toolbar .columns { @@ -16,26 +16,34 @@ margin-top: 10px; margin-bottom: 10px; } + .bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group { display: inline-block; margin-left: -1px !important; } + +.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group > .btn { + border-radius: 0; +} + .bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group:first-child > .btn { border-top-left-radius: 4px; border-bottom-left-radius: 4px; } + .bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group:last-child > .btn { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } -.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group > .btn { - border-radius: 0; -} + .bootstrap-table .fixed-table-toolbar .columns .dropdown-menu { text-align: left; max-height: 300px; overflow: auto; + -ms-overflow-style: scrollbar; + z-index: 1001; } + .bootstrap-table .fixed-table-toolbar .columns label { display: block; padding: 3px 20px; @@ -43,68 +51,188 @@ font-weight: normal; line-height: 1.428571429; } + .bootstrap-table .fixed-table-toolbar .columns-left { margin-right: 5px; } + .bootstrap-table .fixed-table-toolbar .columns-right { margin-left: 5px; } + .bootstrap-table .fixed-table-toolbar .pull-right .dropdown-menu { right: 0; left: auto; } + .bootstrap-table .fixed-table-container { position: relative; clear: both; } + +.bootstrap-table .fixed-table-container .table { + width: 100%; + margin-bottom: 0 !important; +} + +.bootstrap-table .fixed-table-container .table th, +.bootstrap-table .fixed-table-container .table td { + vertical-align: middle; + box-sizing: border-box; +} + +.bootstrap-table .fixed-table-container .table thead th { + vertical-align: bottom; + padding: 0; + margin: 0; +} + +.bootstrap-table .fixed-table-container .table thead th:focus { + outline: 0 solid transparent; +} + +.bootstrap-table .fixed-table-container .table thead th.detail { + width: 30px; +} + +.bootstrap-table .fixed-table-container .table thead th .th-inner { + padding: 0.75rem; + vertical-align: bottom; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.bootstrap-table .fixed-table-container .table thead th .sortable { + cursor: pointer; + background-position: right; + background-repeat: no-repeat; + padding-right: 30px !important; +} + +.bootstrap-table .fixed-table-container .table thead th .both { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC"); +} + +.bootstrap-table .fixed-table-container .table thead th .asc { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=="); +} + +.bootstrap-table .fixed-table-container .table thead th .desc { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= "); +} + +.bootstrap-table .fixed-table-container .table tbody tr.selected td { + background-color: rgba(0, 0, 0, 0.075); +} + +.bootstrap-table .fixed-table-container .table tbody tr.no-records-found td { + text-align: center; +} + +.bootstrap-table .fixed-table-container .table tbody tr .card-view { + display: flex; +} + +.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title { + font-weight: bold; + display: inline-block; + min-width: 30%; + width: auto !important; + text-align: left !important; +} + +.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-value { + width: 100% !important; +} + +.bootstrap-table .fixed-table-container .table .bs-checkbox { + text-align: center; +} + +.bootstrap-table .fixed-table-container .table .bs-checkbox label { + margin-bottom: 0; +} + +.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type="radio"], +.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type="checkbox"] { + margin: 0 auto !important; +} + +.bootstrap-table .fixed-table-container .table.table-sm .th-inner { + padding: 0.3rem; +} + .bootstrap-table .fixed-table-container.fixed-height:not(.has-footer) { border-bottom: 1px solid #dee2e6; } + +.bootstrap-table .fixed-table-container.fixed-height.has-card-view { + border-top: 1px solid #dee2e6; + border-bottom: 1px solid #dee2e6; +} + .bootstrap-table .fixed-table-container.fixed-height .fixed-table-border { border-left: 1px solid #dee2e6; border-right: 1px solid #dee2e6; } + .bootstrap-table .fixed-table-container.fixed-height .table thead th { border-bottom: 1px solid #dee2e6; } + .bootstrap-table .fixed-table-container.fixed-height .table-dark thead th { border-bottom: 1px solid #32383e; } + .bootstrap-table .fixed-table-container .fixed-table-header { overflow: hidden; } + .bootstrap-table .fixed-table-container .fixed-table-body { overflow-x: auto; overflow-y: auto; height: 100%; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading { align-items: center; background: #fff; - display: none; + display: flex; justify-content: center; position: absolute; bottom: 0; width: 100%; z-index: 1000; + transition: visibility 0s, opacity 0.15s ease-in-out; + opacity: 0; + visibility: hidden; } + +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.open { + visibility: visible; + opacity: 1; +} + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap { align-items: baseline; display: flex; justify-content: center; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .loading-text { - font-size: 2rem; margin-right: 6px; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap { align-items: center; display: flex; justify-content: center; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot, -.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap:after, -.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap:before { +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after, +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::before { content: ""; animation-duration: 1.5s; animation-iteration-count: infinite; @@ -117,139 +245,102 @@ opacity: 0; width: 5px; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot { animation-delay: 0.3s; } -.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap:after { + +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after { animation-delay: 0.6s; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark { background: #212529; } + .bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-dot, -.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap:after, -.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap:before { +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::after, +.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::before { background: #fff; } -.bootstrap-table .fixed-table-container .table { - width: 100%; - margin-bottom: 0 !important; -} -.bootstrap-table .fixed-table-container .table th, -.bootstrap-table .fixed-table-container .table td { - vertical-align: middle; - box-sizing: border-box; -} -.bootstrap-table .fixed-table-container .table thead th { - vertical-align: bottom; - padding: 0; - margin: 0; -} -.bootstrap-table .fixed-table-container .table thead th:focus { - outline: 0 solid transparent; -} -.bootstrap-table .fixed-table-container .table thead th.detail { - width: 30px; -} -.bootstrap-table .fixed-table-container .table thead th .th-inner { - padding: 0.75rem; - vertical-align: bottom; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.bootstrap-table .fixed-table-container .table thead th .sortable { - cursor: pointer; - background-position: right; - background-repeat: no-repeat; - padding-right: 30px; -} -.bootstrap-table .fixed-table-container .table thead th .both { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC"); -} -.bootstrap-table .fixed-table-container .table thead th .asc { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=="); -} -.bootstrap-table .fixed-table-container .table thead th .desc { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= "); -} -.bootstrap-table .fixed-table-container .table tbody tr.selected td { - background-color: rgba(0, 0, 0, 0.075); -} -.bootstrap-table .fixed-table-container .table tbody tr.no-records-found { - text-align: center; -} -.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title { - font-weight: bold; - display: inline-block; - min-width: 30%; - text-align: left !important; -} -.bootstrap-table .fixed-table-container .table .bs-checkbox { - text-align: center; -} -.bootstrap-table .fixed-table-container .table input[type=radio], -.bootstrap-table .fixed-table-container .table input[type=checkbox] { - margin: 0 auto !important; -} -.bootstrap-table .fixed-table-container .table.table-sm .th-inner { - padding: 0.3rem; -} + .bootstrap-table .fixed-table-container .fixed-table-footer { overflow: hidden; } -.bootstrap-table .fixed-table-pagination:after { + +.bootstrap-table .fixed-table-pagination::after { content: ""; display: block; clear: both; } + .bootstrap-table .fixed-table-pagination > .pagination-detail, .bootstrap-table .fixed-table-pagination > .pagination { margin-top: 10px; margin-bottom: 10px; } + .bootstrap-table .fixed-table-pagination > .pagination-detail .pagination-info { line-height: 34px; margin-right: 5px; } + .bootstrap-table .fixed-table-pagination > .pagination-detail .page-list { display: inline-block; } + .bootstrap-table .fixed-table-pagination > .pagination-detail .page-list .btn-group { position: relative; display: inline-block; vertical-align: middle; } + .bootstrap-table .fixed-table-pagination > .pagination-detail .page-list .btn-group .dropdown-menu { margin-bottom: 0; } + .bootstrap-table .fixed-table-pagination > .pagination ul.pagination { margin: 0; } -.bootstrap-table .fixed-table-pagination > .pagination ul.pagination a { - padding: 6px 12px; - line-height: 1.428571429; -} + .bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a { color: #c8c8c8; } -.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a:before { - content: "⬅"; + +.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a::before { + content: '\2B05'; } -.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a:after { - content: "➡"; + +.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a::after { + content: '\27A1'; } + .bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.disabled a { pointer-events: none; cursor: default; } + .bootstrap-table.fullscreen { position: fixed; top: 0; left: 0; z-index: 1050; width: 100% !important; - background: #FFF; + background: #fff; + height: calc(100vh); + overflow-y: scroll; +} + +.bootstrap-table.bootstrap4 .pagination-lg .page-link, .bootstrap-table.bootstrap5 .pagination-lg .page-link { + padding: .5rem 1rem; +} + +.bootstrap-table.bootstrap5 .float-left { + float: left; +} + +.bootstrap-table.bootstrap5 .float-right { + float: right; } /* calculate scrollbar width */ @@ -278,5 +369,3 @@ div.fixed-table-scroll-outer { opacity: 0; } } - -/*# sourceMappingURL=bootstrap-table.css.map */ diff --git a/InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js b/InvenTree/InvenTree/static/bootstrap-table/bootstrap-table.js similarity index 100% rename from InvenTree/InvenTree/static/script/bootstrap/bootstrap-table.js rename to InvenTree/InvenTree/static/bootstrap-table/bootstrap-table.js diff --git a/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js b/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js index e33307f565..37bf86ad25 100644 --- a/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js +++ b/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.js @@ -1,116 +1,1779 @@ -/** - * @author: general - * @website: note.generals.space - * @email: generals.space@gmail.com - * @github: https://github.com/generals-space/bootstrap-table-addrbar - * @update: zhixin wen - */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) : + typeof define === 'function' && define.amd ? define(['jquery'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jQuery)); +}(this, (function ($) { 'use strict'; + + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + + var $__default = /*#__PURE__*/_interopDefaultLegacy($); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; + } + + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; + } + + function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArrayLimit(arr, i) { + if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var check = function (it) { + return it && it.Math == Math && it; + }; + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global_1 = + /* global globalThis -- safe */ + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof commonjsGlobal == 'object' && commonjsGlobal) || + // eslint-disable-next-line no-new-func -- fallback + (function () { return this; })() || Function('return this')(); + + var fails = function (exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + + // Detect IE8's incomplete defineProperty implementation + var descriptors = !fails(function () { + return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; + }); + + var nativePropertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor; + + // Nashorn ~ JDK8 bug + var NASHORN_BUG = getOwnPropertyDescriptor$1 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1); + + // `Object.prototype.propertyIsEnumerable` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable + var f$4 = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor$1(this, V); + return !!descriptor && descriptor.enumerable; + } : nativePropertyIsEnumerable; + + var objectPropertyIsEnumerable = { + f: f$4 + }; + + var createPropertyDescriptor = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + + var toString = {}.toString; + + var classofRaw = function (it) { + return toString.call(it).slice(8, -1); + }; + + var split = ''.split; + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var indexedObject = fails(function () { + // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 + // eslint-disable-next-line no-prototype-builtins -- safe + return !Object('z').propertyIsEnumerable(0); + }) ? function (it) { + return classofRaw(it) == 'String' ? split.call(it, '') : Object(it); + } : Object; + + // `RequireObjectCoercible` abstract operation + // https://tc39.es/ecma262/#sec-requireobjectcoercible + var requireObjectCoercible = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; + }; + + // toObject with fallback for non-array-like ES3 strings + + + + var toIndexedObject = function (it) { + return indexedObject(requireObjectCoercible(it)); + }; + + var isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; + + // `ToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-toprimitive + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + var toPrimitive = function (input, PREFERRED_STRING) { + if (!isObject(input)) return input; + var fn, val; + if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; + if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + throw TypeError("Can't convert object to primitive value"); + }; + + var hasOwnProperty = {}.hasOwnProperty; + + var has$1 = function (it, key) { + return hasOwnProperty.call(it, key); + }; + + var document = global_1.document; + // typeof document.createElement is 'object' in old IE + var EXISTS = isObject(document) && isObject(document.createElement); + + var documentCreateElement = function (it) { + return EXISTS ? document.createElement(it) : {}; + }; + + // Thank's IE8 for his funny defineProperty + var ie8DomDefine = !descriptors && !fails(function () { + return Object.defineProperty(documentCreateElement('div'), 'a', { + get: function () { return 7; } + }).a != 7; + }); + + var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + var f$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject(O); + P = toPrimitive(P, true); + if (ie8DomDefine) try { + return nativeGetOwnPropertyDescriptor(O, P); + } catch (error) { /* empty */ } + if (has$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]); + }; + + var objectGetOwnPropertyDescriptor = { + f: f$3 + }; + + var anObject = function (it) { + if (!isObject(it)) { + throw TypeError(String(it) + ' is not an object'); + } return it; + }; + + var nativeDefineProperty = Object.defineProperty; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (ie8DomDefine) try { + return nativeDefineProperty(O, P, Attributes); + } catch (error) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + + var objectDefineProperty = { + f: f$2 + }; + + var createNonEnumerableProperty = descriptors ? function (object, key, value) { + return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + + var setGlobal = function (key, value) { + try { + createNonEnumerableProperty(global_1, key, value); + } catch (error) { + global_1[key] = value; + } return value; + }; + + var SHARED = '__core-js_shared__'; + var store$1 = global_1[SHARED] || setGlobal(SHARED, {}); + + var sharedStore = store$1; + + var functionToString = Function.toString; + + // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper + if (typeof sharedStore.inspectSource != 'function') { + sharedStore.inspectSource = function (it) { + return functionToString.call(it); + }; + } + + var inspectSource = sharedStore.inspectSource; + + var WeakMap$1 = global_1.WeakMap; + + var nativeWeakMap = typeof WeakMap$1 === 'function' && /native code/.test(inspectSource(WeakMap$1)); + + var shared = createCommonjsModule(function (module) { + (module.exports = function (key, value) { + return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: '3.9.1', + mode: 'global', + copyright: '© 2021 Denis Pushkarev (zloirock.ru)' + }); + }); + + var id = 0; + var postfix = Math.random(); + + var uid = function (key) { + return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36); + }; + + var keys$1 = shared('keys'); + + var sharedKey = function (key) { + return keys$1[key] || (keys$1[key] = uid(key)); + }; + + var hiddenKeys$1 = {}; + + var WeakMap = global_1.WeakMap; + var set, get, has; + + var enforce = function (it) { + return has(it) ? get(it) : set(it, {}); + }; + + var getterFor = function (TYPE) { + return function (it) { + var state; + if (!isObject(it) || (state = get(it)).type !== TYPE) { + throw TypeError('Incompatible receiver, ' + TYPE + ' required'); + } return state; + }; + }; + + if (nativeWeakMap) { + var store = sharedStore.state || (sharedStore.state = new WeakMap()); + var wmget = store.get; + var wmhas = store.has; + var wmset = store.set; + set = function (it, metadata) { + metadata.facade = it; + wmset.call(store, it, metadata); + return metadata; + }; + get = function (it) { + return wmget.call(store, it) || {}; + }; + has = function (it) { + return wmhas.call(store, it); + }; + } else { + var STATE = sharedKey('state'); + hiddenKeys$1[STATE] = true; + set = function (it, metadata) { + metadata.facade = it; + createNonEnumerableProperty(it, STATE, metadata); + return metadata; + }; + get = function (it) { + return has$1(it, STATE) ? it[STATE] : {}; + }; + has = function (it) { + return has$1(it, STATE); + }; + } + + var internalState = { + set: set, + get: get, + has: has, + enforce: enforce, + getterFor: getterFor + }; + + var redefine = createCommonjsModule(function (module) { + var getInternalState = internalState.get; + var enforceInternalState = internalState.enforce; + var TEMPLATE = String(String).split('String'); + + (module.exports = function (O, key, value, options) { + var unsafe = options ? !!options.unsafe : false; + var simple = options ? !!options.enumerable : false; + var noTargetGet = options ? !!options.noTargetGet : false; + var state; + if (typeof value == 'function') { + if (typeof key == 'string' && !has$1(value, 'name')) { + createNonEnumerableProperty(value, 'name', key); + } + state = enforceInternalState(value); + if (!state.source) { + state.source = TEMPLATE.join(typeof key == 'string' ? key : ''); + } + } + if (O === global_1) { + if (simple) O[key] = value; + else setGlobal(key, value); + return; + } else if (!unsafe) { + delete O[key]; + } else if (!noTargetGet && O[key]) { + simple = true; + } + if (simple) O[key] = value; + else createNonEnumerableProperty(O, key, value); + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + })(Function.prototype, 'toString', function toString() { + return typeof this == 'function' && getInternalState(this).source || inspectSource(this); + }); + }); + + var path = global_1; + + var aFunction = function (variable) { + return typeof variable == 'function' ? variable : undefined; + }; + + var getBuiltIn = function (namespace, method) { + return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace]) + : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; + }; + + var ceil = Math.ceil; + var floor$1 = Math.floor; + + // `ToInteger` abstract operation + // https://tc39.es/ecma262/#sec-tointeger + var toInteger = function (argument) { + return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor$1 : ceil)(argument); + }; + + var min$2 = Math.min; + + // `ToLength` abstract operation + // https://tc39.es/ecma262/#sec-tolength + var toLength = function (argument) { + return argument > 0 ? min$2(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 + }; + + var max$1 = Math.max; + var min$1 = Math.min; + + // Helper for a popular repeating case of the spec: + // Let integer be ? ToInteger(index). + // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). + var toAbsoluteIndex = function (index, length) { + var integer = toInteger(index); + return integer < 0 ? max$1(integer + length, 0) : min$1(integer, length); + }; + + // `Array.prototype.{ indexOf, includes }` methods implementation + var createMethod$2 = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare -- NaN check + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare -- NaN check + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + + var arrayIncludes = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod$2(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod$2(false) + }; + + var indexOf = arrayIncludes.indexOf; + + + var objectKeysInternal = function (object, names) { + var O = toIndexedObject(object); + var i = 0; + var result = []; + var key; + for (key in O) !has$1(hiddenKeys$1, key) && has$1(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has$1(O, key = names[i++])) { + ~indexOf(result, key) || result.push(key); + } + return result; + }; + + // IE8- don't enum bug keys + var enumBugKeys = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + var hiddenKeys = enumBugKeys.concat('length', 'prototype'); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return objectKeysInternal(O, hiddenKeys); + }; + + var objectGetOwnPropertyNames = { + f: f$1 + }; + + var f = Object.getOwnPropertySymbols; + + var objectGetOwnPropertySymbols = { + f: f + }; + + // all object keys, includes non-enumerable and symbols + var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { + var keys = objectGetOwnPropertyNames.f(anObject(it)); + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys; + }; + + var copyConstructorProperties = function (target, source) { + var keys = ownKeys(source); + var defineProperty = objectDefineProperty.f; + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!has$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + }; + + var replacement = /#|\.prototype\./; + + var isForced = function (feature, detection) { + var value = data[normalize(feature)]; + return value == POLYFILL ? true + : value == NATIVE ? false + : typeof detection == 'function' ? fails(detection) + : !!detection; + }; + + var normalize = isForced.normalize = function (string) { + return String(string).replace(replacement, '.').toLowerCase(); + }; + + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = 'N'; + var POLYFILL = isForced.POLYFILL = 'P'; + + var isForced_1 = isForced; + + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + + + + + -($ => { /* - * function: 获取浏览器地址栏中的指定参数. - * key: 参数名 - * url: 默认为当前地址栏 - */ - function _GET (key, url = window.location.search) { + options.target - name of the target object + options.global - target is the global object + options.stat - export as static methods of target + options.proto - export as prototype methods of target + options.real - real prototype method for the `pure` version + options.forced - export even if the native feature is available + options.bind - bind methods to the target, required for the `pure` version + options.wrap - wrap constructors to preventing global pollution, required for the `pure` version + options.unsafe - use the simple assignment of property instead of delete + defineProperty + options.sham - add a flag to not completely full polyfills + options.enumerable - export as enumerable property + options.noTargetGet - prevent calling a getter on target + */ + var _export = function (options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = global_1; + } else if (STATIC) { + target = global_1[TARGET] || setGlobal(TARGET, {}); + } else { + target = (global_1[TARGET] || {}).prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.noTargetGet) { + descriptor = getOwnPropertyDescriptor(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); + // contained in target + if (!FORCED && targetProperty !== undefined) { + if (typeof sourceProperty === typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + // add a flag to not completely full polyfills + if (options.sham || (targetProperty && targetProperty.sham)) { + createNonEnumerableProperty(sourceProperty, 'sham', true); + } + // extend global + redefine(target, key, sourceProperty, options); + } + }; + + // `RegExp.prototype.flags` getter implementation + // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags + var regexpFlags = function () { + var that = anObject(this); + var result = ''; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.dotAll) result += 's'; + if (that.unicode) result += 'u'; + if (that.sticky) result += 'y'; + return result; + }; + + // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError, + // so we use an intermediate function. + function RE(s, f) { + return RegExp(s, f); + } + + var UNSUPPORTED_Y$2 = fails(function () { + // babel-minify transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError + var re = RE('a', 'y'); + re.lastIndex = 2; + return re.exec('abcd') != null; + }); + + var BROKEN_CARET = fails(function () { + // https://bugzilla.mozilla.org/show_bug.cgi?id=773687 + var re = RE('^r', 'gy'); + re.lastIndex = 2; + return re.exec('str') != null; + }); + + var regexpStickyHelpers = { + UNSUPPORTED_Y: UNSUPPORTED_Y$2, + BROKEN_CARET: BROKEN_CARET + }; + + var nativeExec = RegExp.prototype.exec; + // This always refers to the native implementation, because the + // String#replace polyfill uses ./fix-regexp-well-known-symbol-logic.js, + // which loads this file before patching the method. + var nativeReplace = String.prototype.replace; + + var patchedExec = nativeExec; + + var UPDATES_LAST_INDEX_WRONG = (function () { + var re1 = /a/; + var re2 = /b*/g; + nativeExec.call(re1, 'a'); + nativeExec.call(re2, 'a'); + return re1.lastIndex !== 0 || re2.lastIndex !== 0; + })(); + + var UNSUPPORTED_Y$1 = regexpStickyHelpers.UNSUPPORTED_Y || regexpStickyHelpers.BROKEN_CARET; + + // nonparticipating capturing group, copied from es5-shim's String#split patch. + // eslint-disable-next-line regexp/no-assertion-capturing-group, regexp/no-empty-group -- required for testing + var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined; + + var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$1; + + if (PATCH) { + patchedExec = function exec(str) { + var re = this; + var lastIndex, reCopy, match, i; + var sticky = UNSUPPORTED_Y$1 && re.sticky; + var flags = regexpFlags.call(re); + var source = re.source; + var charsAdded = 0; + var strCopy = str; + + if (sticky) { + flags = flags.replace('y', ''); + if (flags.indexOf('g') === -1) { + flags += 'g'; + } + + strCopy = String(str).slice(re.lastIndex); + // Support anchored sticky behavior. + if (re.lastIndex > 0 && (!re.multiline || re.multiline && str[re.lastIndex - 1] !== '\n')) { + source = '(?: ' + source + ')'; + strCopy = ' ' + strCopy; + charsAdded++; + } + // ^(? + rx + ) is needed, in combination with some str slicing, to + // simulate the 'y' flag. + reCopy = new RegExp('^(?:' + source + ')', flags); + } + + if (NPCG_INCLUDED) { + reCopy = new RegExp('^' + source + '$(?!\\s)', flags); + } + if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex; + + match = nativeExec.call(sticky ? reCopy : re, strCopy); + + if (sticky) { + if (match) { + match.input = match.input.slice(charsAdded); + match[0] = match[0].slice(charsAdded); + match.index = re.lastIndex; + re.lastIndex += match[0].length; + } else re.lastIndex = 0; + } else if (UPDATES_LAST_INDEX_WRONG && match) { + re.lastIndex = re.global ? match.index + match[0].length : lastIndex; + } + if (NPCG_INCLUDED && match && match.length > 1) { + // Fix browsers whose `exec` methods don't consistently return `undefined` + // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/ + nativeReplace.call(match[0], reCopy, function () { + for (i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) match[i] = undefined; + } + }); + } + + return match; + }; + } + + var regexpExec = patchedExec; + + // `RegExp.prototype.exec` method + // https://tc39.es/ecma262/#sec-regexp.prototype.exec + _export({ target: 'RegExp', proto: true, forced: /./.exec !== regexpExec }, { + exec: regexpExec + }); + + var engineIsNode = classofRaw(global_1.process) == 'process'; + + var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; + + var process = global_1.process; + var versions = process && process.versions; + var v8 = versions && versions.v8; + var match, version; + + if (v8) { + match = v8.split('.'); + version = match[0] + match[1]; + } else if (engineUserAgent) { + match = engineUserAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = engineUserAgent.match(/Chrome\/(\d+)/); + if (match) version = match[1]; + } + } + + var engineV8Version = version && +version; + + var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { + /* global Symbol -- required for testing */ + return !Symbol.sham && + // Chrome 38 Symbol has incorrect toString conversion + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41); + }); + + var useSymbolAsUid = nativeSymbol + /* global Symbol -- safe */ + && !Symbol.sham + && typeof Symbol.iterator == 'symbol'; + + var WellKnownSymbolsStore = shared('wks'); + var Symbol$1 = global_1.Symbol; + var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; + + var wellKnownSymbol = function (name) { + if (!has$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { + if (nativeSymbol && has$1(Symbol$1, name)) { + WellKnownSymbolsStore[name] = Symbol$1[name]; + } else { + WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + } + } return WellKnownSymbolsStore[name]; + }; + + // TODO: Remove from `core-js@4` since it's moved to entry points + + + + + + + + var SPECIES$3 = wellKnownSymbol('species'); + + var REPLACE_SUPPORTS_NAMED_GROUPS = !fails(function () { + // #replace needs built-in support for named groups. + // #match works fine because it just return the exec results, even if it has + // a "grops" property. + var re = /./; + re.exec = function () { + var result = []; + result.groups = { a: '7' }; + return result; + }; + return ''.replace(re, '$') !== '7'; + }); + + // IE <= 11 replaces $0 with the whole match, as if it was $& + // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0 + var REPLACE_KEEPS_$0 = (function () { + return 'a'.replace(/./, '$0') === '$0'; + })(); + + var REPLACE = wellKnownSymbol('replace'); + // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string + var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () { + if (/./[REPLACE]) { + return /./[REPLACE]('a', '$0') === ''; + } + return false; + })(); + + // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec + // Weex JS has frozen built-in prototypes, so use try / catch wrapper + var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () { + // eslint-disable-next-line regexp/no-empty-group -- required for testing + var re = /(?:)/; + var originalExec = re.exec; + re.exec = function () { return originalExec.apply(this, arguments); }; + var result = 'ab'.split(re); + return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b'; + }); + + var fixRegexpWellKnownSymbolLogic = function (KEY, length, exec, sham) { + var SYMBOL = wellKnownSymbol(KEY); + + var DELEGATES_TO_SYMBOL = !fails(function () { + // String methods call symbol-named RegEp methods + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) != 7; + }); + + var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () { + // Symbol-named RegExp methods call .exec + var execCalled = false; + var re = /a/; + + if (KEY === 'split') { + // We can't use real regex here since it causes deoptimization + // and serious performance degradation in V8 + // https://github.com/zloirock/core-js/issues/306 + re = {}; + // RegExp[@@split] doesn't call the regex's exec method, but first creates + // a new one. We need to return the patched regex when creating the new one. + re.constructor = {}; + re.constructor[SPECIES$3] = function () { return re; }; + re.flags = ''; + re[SYMBOL] = /./[SYMBOL]; + } + + re.exec = function () { execCalled = true; return null; }; + + re[SYMBOL](''); + return !execCalled; + }); + + if ( + !DELEGATES_TO_SYMBOL || + !DELEGATES_TO_EXEC || + (KEY === 'replace' && !( + REPLACE_SUPPORTS_NAMED_GROUPS && + REPLACE_KEEPS_$0 && + !REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE + )) || + (KEY === 'split' && !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC) + ) { + var nativeRegExpMethod = /./[SYMBOL]; + var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) { + if (regexp.exec === regexpExec) { + if (DELEGATES_TO_SYMBOL && !forceStringMethod) { + // The native String method already delegates to @@method (this + // polyfilled function), leasing to infinite recursion. + // We avoid it by directly calling the native @@method method. + return { done: true, value: nativeRegExpMethod.call(regexp, str, arg2) }; + } + return { done: true, value: nativeMethod.call(str, regexp, arg2) }; + } + return { done: false }; + }, { + REPLACE_KEEPS_$0: REPLACE_KEEPS_$0, + REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE: REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE + }); + var stringMethod = methods[0]; + var regexMethod = methods[1]; + + redefine(String.prototype, KEY, stringMethod); + redefine(RegExp.prototype, SYMBOL, length == 2 + // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) + // 21.2.5.11 RegExp.prototype[@@split](string, limit) + ? function (string, arg) { return regexMethod.call(string, this, arg); } + // 21.2.5.6 RegExp.prototype[@@match](string) + // 21.2.5.9 RegExp.prototype[@@search](string) + : function (string) { return regexMethod.call(string, this); } + ); + } + + if (sham) createNonEnumerableProperty(RegExp.prototype[SYMBOL], 'sham', true); + }; + + // `SameValue` abstract operation + // https://tc39.es/ecma262/#sec-samevalue + var sameValue = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare -- NaN check + return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; + }; + + // `RegExpExec` abstract operation + // https://tc39.es/ecma262/#sec-regexpexec + var regexpExecAbstract = function (R, S) { + var exec = R.exec; + if (typeof exec === 'function') { + var result = exec.call(R, S); + if (typeof result !== 'object') { + throw TypeError('RegExp exec method returned something other than an Object or null'); + } + return result; + } + + if (classofRaw(R) !== 'RegExp') { + throw TypeError('RegExp#exec called on incompatible receiver'); + } + + return regexpExec.call(R, S); + }; + + // @@search logic + fixRegexpWellKnownSymbolLogic('search', 1, function (SEARCH, nativeSearch, maybeCallNative) { + return [ + // `String.prototype.search` method + // https://tc39.es/ecma262/#sec-string.prototype.search + function search(regexp) { + var O = requireObjectCoercible(this); + var searcher = regexp == undefined ? undefined : regexp[SEARCH]; + return searcher !== undefined ? searcher.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, + // `RegExp.prototype[@@search]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@search + function (regexp) { + var res = maybeCallNative(nativeSearch, regexp, this); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + + var previousLastIndex = rx.lastIndex; + if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0; + var result = regexpExecAbstract(rx, S); + if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex; + return result === null ? -1 : result.index; + } + ]; + }); + + var aPossiblePrototype = function (it) { + if (!isObject(it) && it !== null) { + throw TypeError("Can't set " + String(it) + ' as a prototype'); + } return it; + }; + + /* eslint-disable no-proto -- safe */ + + + + // `Object.setPrototypeOf` method + // https://tc39.es/ecma262/#sec-object.setprototypeof + // Works with __proto__ only. Old v8 can't work with null proto objects. + var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () { + var CORRECT_SETTER = false; + var test = {}; + var setter; + try { + setter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set; + setter.call(test, []); + CORRECT_SETTER = test instanceof Array; + } catch (error) { /* empty */ } + return function setPrototypeOf(O, proto) { + anObject(O); + aPossiblePrototype(proto); + if (CORRECT_SETTER) setter.call(O, proto); + else O.__proto__ = proto; + return O; + }; + }() : undefined); + + // makes subclassing work correct for wrapped built-ins + var inheritIfRequired = function ($this, dummy, Wrapper) { + var NewTarget, NewTargetPrototype; + if ( + // it can work only with native `setPrototypeOf` + objectSetPrototypeOf && + // we haven't completely correct pre-ES6 way for getting `new.target`, so use this + typeof (NewTarget = dummy.constructor) == 'function' && + NewTarget !== Wrapper && + isObject(NewTargetPrototype = NewTarget.prototype) && + NewTargetPrototype !== Wrapper.prototype + ) objectSetPrototypeOf($this, NewTargetPrototype); + return $this; + }; + + var MATCH$1 = wellKnownSymbol('match'); + + // `IsRegExp` abstract operation + // https://tc39.es/ecma262/#sec-isregexp + var isRegexp = function (it) { + var isRegExp; + return isObject(it) && ((isRegExp = it[MATCH$1]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp'); + }; + + var SPECIES$2 = wellKnownSymbol('species'); + + var setSpecies = function (CONSTRUCTOR_NAME) { + var Constructor = getBuiltIn(CONSTRUCTOR_NAME); + var defineProperty = objectDefineProperty.f; + + if (descriptors && Constructor && !Constructor[SPECIES$2]) { + defineProperty(Constructor, SPECIES$2, { + configurable: true, + get: function () { return this; } + }); + } + }; + + var defineProperty = objectDefineProperty.f; + var getOwnPropertyNames = objectGetOwnPropertyNames.f; + + + + + + var setInternalState = internalState.set; + + + + var MATCH = wellKnownSymbol('match'); + var NativeRegExp = global_1.RegExp; + var RegExpPrototype$1 = NativeRegExp.prototype; + var re1 = /a/g; + var re2 = /a/g; + + // "new" should create a new object, old webkit bug + var CORRECT_NEW = new NativeRegExp(re1) !== re1; + + var UNSUPPORTED_Y = regexpStickyHelpers.UNSUPPORTED_Y; + + var FORCED$1 = descriptors && isForced_1('RegExp', (!CORRECT_NEW || UNSUPPORTED_Y || fails(function () { + re2[MATCH] = false; + // RegExp constructor can alter flags and IsRegExp works correct with @@match + return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i'; + }))); + + // `RegExp` constructor + // https://tc39.es/ecma262/#sec-regexp-constructor + if (FORCED$1) { + var RegExpWrapper = function RegExp(pattern, flags) { + var thisIsRegExp = this instanceof RegExpWrapper; + var patternIsRegExp = isRegexp(pattern); + var flagsAreUndefined = flags === undefined; + var sticky; + + if (!thisIsRegExp && patternIsRegExp && pattern.constructor === RegExpWrapper && flagsAreUndefined) { + return pattern; + } + + if (CORRECT_NEW) { + if (patternIsRegExp && !flagsAreUndefined) pattern = pattern.source; + } else if (pattern instanceof RegExpWrapper) { + if (flagsAreUndefined) flags = regexpFlags.call(pattern); + pattern = pattern.source; + } + + if (UNSUPPORTED_Y) { + sticky = !!flags && flags.indexOf('y') > -1; + if (sticky) flags = flags.replace(/y/g, ''); + } + + var result = inheritIfRequired( + CORRECT_NEW ? new NativeRegExp(pattern, flags) : NativeRegExp(pattern, flags), + thisIsRegExp ? this : RegExpPrototype$1, + RegExpWrapper + ); + + if (UNSUPPORTED_Y && sticky) setInternalState(result, { sticky: sticky }); + + return result; + }; + var proxy = function (key) { + key in RegExpWrapper || defineProperty(RegExpWrapper, key, { + configurable: true, + get: function () { return NativeRegExp[key]; }, + set: function (it) { NativeRegExp[key] = it; } + }); + }; + var keys = getOwnPropertyNames(NativeRegExp); + var index = 0; + while (keys.length > index) proxy(keys[index++]); + RegExpPrototype$1.constructor = RegExpWrapper; + RegExpWrapper.prototype = RegExpPrototype$1; + redefine(global_1, 'RegExp', RegExpWrapper); + } + + // https://tc39.es/ecma262/#sec-get-regexp-@@species + setSpecies('RegExp'); + + var TO_STRING = 'toString'; + var RegExpPrototype = RegExp.prototype; + var nativeToString = RegExpPrototype[TO_STRING]; + + var NOT_GENERIC = fails(function () { return nativeToString.call({ source: 'a', flags: 'b' }) != '/a/b'; }); + // FF44- RegExp#toString has a wrong name + var INCORRECT_NAME = nativeToString.name != TO_STRING; + + // `RegExp.prototype.toString` method + // https://tc39.es/ecma262/#sec-regexp.prototype.tostring + if (NOT_GENERIC || INCORRECT_NAME) { + redefine(RegExp.prototype, TO_STRING, function toString() { + var R = anObject(this); + var p = String(R.source); + var rf = R.flags; + var f = String(rf === undefined && R instanceof RegExp && !('flags' in RegExpPrototype) ? regexpFlags.call(R) : rf); + return '/' + p + '/' + f; + }, { unsafe: true }); + } + + // `String.prototype.{ codePointAt, at }` methods implementation + var createMethod$1 = function (CONVERT_TO_STRING) { + return function ($this, pos) { + var S = String(requireObjectCoercible($this)); + var position = toInteger(pos); + var size = S.length; + var first, second; + if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined; + first = S.charCodeAt(position); + return first < 0xD800 || first > 0xDBFF || position + 1 === size + || (second = S.charCodeAt(position + 1)) < 0xDC00 || second > 0xDFFF + ? CONVERT_TO_STRING ? S.charAt(position) : first + : CONVERT_TO_STRING ? S.slice(position, position + 2) : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000; + }; + }; + + var stringMultibyte = { + // `String.prototype.codePointAt` method + // https://tc39.es/ecma262/#sec-string.prototype.codepointat + codeAt: createMethod$1(false), + // `String.prototype.at` method + // https://github.com/mathiasbynens/String.prototype.at + charAt: createMethod$1(true) + }; + + var charAt = stringMultibyte.charAt; + + // `AdvanceStringIndex` abstract operation + // https://tc39.es/ecma262/#sec-advancestringindex + var advanceStringIndex = function (S, index, unicode) { + return index + (unicode ? charAt(S, index).length : 1); + }; + + // @@match logic + fixRegexpWellKnownSymbolLogic('match', 1, function (MATCH, nativeMatch, maybeCallNative) { + return [ + // `String.prototype.match` method + // https://tc39.es/ecma262/#sec-string.prototype.match + function match(regexp) { + var O = requireObjectCoercible(this); + var matcher = regexp == undefined ? undefined : regexp[MATCH]; + return matcher !== undefined ? matcher.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); + }, + // `RegExp.prototype[@@match]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@match + function (regexp) { + var res = maybeCallNative(nativeMatch, regexp, this); + if (res.done) return res.value; + + var rx = anObject(regexp); + var S = String(this); + + if (!rx.global) return regexpExecAbstract(rx, S); + + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + var A = []; + var n = 0; + var result; + while ((result = regexpExecAbstract(rx, S)) !== null) { + var matchStr = String(result[0]); + A[n] = matchStr; + if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); + n++; + } + return n === 0 ? null : A; + } + ]; + }); + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + var objectKeys = Object.keys || function keys(O) { + return objectKeysInternal(O, enumBugKeys); + }; + + var propertyIsEnumerable = objectPropertyIsEnumerable.f; + + // `Object.{ entries, values }` methods implementation + var createMethod = function (TO_ENTRIES) { + return function (it) { + var O = toIndexedObject(it); + var keys = objectKeys(O); + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) { + key = keys[i++]; + if (!descriptors || propertyIsEnumerable.call(O, key)) { + result.push(TO_ENTRIES ? [key, O[key]] : O[key]); + } + } + return result; + }; + }; + + var objectToArray = { + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + entries: createMethod(true), + // `Object.values` method + // https://tc39.es/ecma262/#sec-object.values + values: createMethod(false) + }; + + var $entries = objectToArray.entries; + + // `Object.entries` method + // https://tc39.es/ecma262/#sec-object.entries + _export({ target: 'Object', stat: true }, { + entries: function entries(O) { + return $entries(O); + } + }); + + // `IsArray` abstract operation + // https://tc39.es/ecma262/#sec-isarray + var isArray = Array.isArray || function isArray(arg) { + return classofRaw(arg) == 'Array'; + }; + + // `ToObject` abstract operation + // https://tc39.es/ecma262/#sec-toobject + var toObject = function (argument) { + return Object(requireObjectCoercible(argument)); + }; + + var createProperty = function (object, key, value) { + var propertyKey = toPrimitive(key); + if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value)); + else object[propertyKey] = value; + }; + + var SPECIES$1 = wellKnownSymbol('species'); + + // `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesCreate = function (originalArray, length) { + var C; + if (isArray(originalArray)) { + C = originalArray.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; + else if (isObject(C)) { + C = C[SPECIES$1]; + if (C === null) C = undefined; + } + } return new (C === undefined ? Array : C)(length === 0 ? 0 : length); + }; + + var SPECIES = wellKnownSymbol('species'); + + var arrayMethodHasSpeciesSupport = function (METHOD_NAME) { + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/677 + return engineV8Version >= 51 || !fails(function () { + var array = []; + var constructor = array.constructor = {}; + constructor[SPECIES] = function () { + return { foo: 1 }; + }; + return array[METHOD_NAME](Boolean).foo !== 1; + }); + }; + + var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable'); + var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; + var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded'; + + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/679 + var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () { + var array = []; + array[IS_CONCAT_SPREADABLE] = false; + return array.concat()[0] !== array; + }); + + var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat'); + + var isConcatSpreadable = function (O) { + if (!isObject(O)) return false; + var spreadable = O[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray(O); + }; + + var FORCED = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT; + + // `Array.prototype.concat` method + // https://tc39.es/ecma262/#sec-array.prototype.concat + // with adding support of @@isConcatSpreadable and @@species + _export({ target: 'Array', proto: true, forced: FORCED }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + concat: function concat(arg) { + var O = toObject(this); + var A = arraySpeciesCreate(O, 0); + var n = 0; + var i, k, length, len, E; + for (i = -1, length = arguments.length; i < length; i++) { + E = i === -1 ? O : arguments[i]; + if (isConcatSpreadable(E)) { + len = toLength(E.length); + if (n + len > MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]); + } else { + if (n >= MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + createProperty(A, n++, E); + } + } + A.length = n; + return A; + } + }); + + var floor = Math.floor; + var replace = ''.replace; + var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g; + var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g; + + // https://tc39.es/ecma262/#sec-getsubstitution + var getSubstitution = function (matched, str, position, captures, namedCaptures, replacement) { + var tailPos = position + matched.length; + var m = captures.length; + var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED; + if (namedCaptures !== undefined) { + namedCaptures = toObject(namedCaptures); + symbols = SUBSTITUTION_SYMBOLS; + } + return replace.call(replacement, symbols, function (match, ch) { + var capture; + switch (ch.charAt(0)) { + case '$': return '$'; + case '&': return matched; + case '`': return str.slice(0, position); + case "'": return str.slice(tailPos); + case '<': + capture = namedCaptures[ch.slice(1, -1)]; + break; + default: // \d\d? + var n = +ch; + if (n === 0) return match; + if (n > m) { + var f = floor(n / 10); + if (f === 0) return match; + if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1); + return match; + } + capture = captures[n - 1]; + } + return capture === undefined ? '' : capture; + }); + }; + + var max = Math.max; + var min = Math.min; + + var maybeToString = function (it) { + return it === undefined ? it : String(it); + }; + + // @@replace logic + fixRegexpWellKnownSymbolLogic('replace', 2, function (REPLACE, nativeReplace, maybeCallNative, reason) { + var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = reason.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE; + var REPLACE_KEEPS_$0 = reason.REPLACE_KEEPS_$0; + var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0'; + + return [ + // `String.prototype.replace` method + // https://tc39.es/ecma262/#sec-string.prototype.replace + function replace(searchValue, replaceValue) { + var O = requireObjectCoercible(this); + var replacer = searchValue == undefined ? undefined : searchValue[REPLACE]; + return replacer !== undefined + ? replacer.call(searchValue, O, replaceValue) + : nativeReplace.call(String(O), searchValue, replaceValue); + }, + // `RegExp.prototype[@@replace]` method + // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace + function (regexp, replaceValue) { + if ( + (!REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE && REPLACE_KEEPS_$0) || + (typeof replaceValue === 'string' && replaceValue.indexOf(UNSAFE_SUBSTITUTE) === -1) + ) { + var res = maybeCallNative(nativeReplace, regexp, this, replaceValue); + if (res.done) return res.value; + } + + var rx = anObject(regexp); + var S = String(this); + + var functionalReplace = typeof replaceValue === 'function'; + if (!functionalReplace) replaceValue = String(replaceValue); + + var global = rx.global; + if (global) { + var fullUnicode = rx.unicode; + rx.lastIndex = 0; + } + var results = []; + while (true) { + var result = regexpExecAbstract(rx, S); + if (result === null) break; + + results.push(result); + if (!global) break; + + var matchStr = String(result[0]); + if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode); + } + + var accumulatedResult = ''; + var nextSourcePosition = 0; + for (var i = 0; i < results.length; i++) { + result = results[i]; + + var matched = String(result[0]); + var position = max(min(toInteger(result.index), S.length), 0); + var captures = []; + // NOTE: This is equivalent to + // captures = result.slice(1).map(maybeToString) + // but for some reason `nativeSlice.call(result, 1, result.length)` (called in + // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and + // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it. + for (var j = 1; j < result.length; j++) captures.push(maybeToString(result[j])); + var namedCaptures = result.groups; + if (functionalReplace) { + var replacerArgs = [matched].concat(captures, position, S); + if (namedCaptures !== undefined) replacerArgs.push(namedCaptures); + var replacement = String(replaceValue.apply(undefined, replacerArgs)); + } else { + replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue); + } + if (position >= nextSourcePosition) { + accumulatedResult += S.slice(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matched.length; + } + } + return accumulatedResult + S.slice(nextSourcePosition); + } + ]; + }); + + /** + * @author: general + * @website: note.generals.space + * @email: generals.space@gmail.com + * @github: https://github.com/generals-space/bootstrap-table-addrbar + * @update: zhixin wen + */ + + /* + * function: 获取浏览器地址栏中的指定参数. + * key: 参数名 + * url: 默认为当前地址栏 + */ + + function _GET(key) { + var url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.location.search; + /* * 注意这里正则表达式的书写方法 * (^|&)key匹配: 直接以key开始或以&key开始的字符串 * 同理(&|$)表示以&结束或是直接结束的字符串 * ...当然, 我并不知道这种用法. */ - const reg = new RegExp(`(^|&)${key}=([^&]*)(&|$)`) - const result = url.substr(1).match(reg) + var reg = new RegExp("(^|&)".concat(key, "=([^&]*)(&|$)")); + var result = url.substr(1).match(reg); if (result) { - return decodeURIComponent(result[2]) + return decodeURIComponent(result[2]); } - return null + + return null; } - /* - * function: 根据给定参数生成url地址 - * var dic = {name: 'genreal', age: 24} - * var url = 'https://www.baidu.com?age=22'; - * _buildUrl(dic, url); - * 将得到"https://www.baidu.com?age=24&name=genreal" - * 哦, 忽略先后顺序吧... - * - * 补充: 可以参考浏览器URLSearchParams对象, 更加方便和强大. - * 考虑到兼容性, 暂时不使用这个工具. - */ + * function: 根据给定参数生成url地址 + * var dic = {name: 'genreal', age: 24} + * var url = 'https://www.baidu.com?age=22'; + * _buildUrl(dic, url); + * 将得到"https://www.baidu.com?age=24&name=genreal" + * 哦, 忽略先后顺序吧... + * + * 补充: 可以参考浏览器URLSearchParams对象, 更加方便和强大. + * 考虑到兼容性, 暂时不使用这个工具. + */ + + + function _buildUrl(dict) { + var url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.location.search; + + for (var _i = 0, _Object$entries = Object.entries(dict); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), + key = _Object$entries$_i[0], + val = _Object$entries$_i[1]; - function _buildUrl (dict, url = window.location.search) { - for (const [key, val] of Object.entries(dict)) { // 搜索name=general这种形式的字符串(&是分隔符) - const pattern = `${key}=([^&]*)` - const targetStr = `${key}=${val}` - + var pattern = "".concat(key, "=([^&]*)"); + var targetStr = "".concat(key, "=").concat(val); + if (val === undefined) continue; /* * 如果目标url中包含了key键, 我们需要将它替换成我们自己的val * 不然就直接添加好了. */ + if (url.match(pattern)) { - const tmp = new RegExp(`(${key}=)([^&]*)`, 'gi') - url = url.replace(tmp, targetStr) + var tmp = new RegExp("(".concat(key, "=)([^&]*)"), 'gi'); + url = url.replace(tmp, targetStr); } else { - const seperator = url.match('[?]') ? '&' : '?' - url = url + seperator + targetStr + var seperator = url.match('[?]') ? '&' : '?'; + url = url + seperator + targetStr; } } + if (location.hash) { - url += location.hash + url += location.hash; } - return url + + return url; + } + /* + * function: _updateHistoryState + * var _prefix = this.options.addrPrefix || '' + * var table = this + * _updateHistoryState( table,_prefix) + * returns void + */ + + + function _updateHistoryState(table, _prefix) { + var params = {}; + params["".concat(_prefix, "page")] = table.options.pageNumber; + params["".concat(_prefix, "size")] = table.options.pageSize; + params["".concat(_prefix, "order")] = table.options.sortOrder; + params["".concat(_prefix, "sort")] = table.options.sortName; + params["".concat(_prefix, "search")] = table.options.searchText; + window.history.pushState({}, '', _buildUrl(params)); } - $.BootstrapTable = class extends $.BootstrapTable { - init () { - // 拥有addrbar选项并且其值为true的才会继续执行 - if (this.options.addrbar) { - // 标志位, 初始加载后关闭 - this.addrbarInit = true - const _prefix = this.options.addrPrefix || '' + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, { + addrbar: false, + addrPrefix: '' + }); - // 优先级排序: 用户指定值最优先, 未指定时从地址栏获取, 未获取到时采用默认值 - this.options.pageSize = this.options.pageSize || ( - _GET(`${_prefix}limit`) ? parseInt(_GET(`${_prefix}limit`)) : $.BootstrapTable.DEFAULTS.pageSize - ) - this.options.pageNumber = this.options.pageNumber || ( - _GET(`${_prefix}page`) ? parseInt(_GET(`${_prefix}page`)) : $.BootstrapTable.DEFAULTS.pageNumber - ) - this.options.sortOrder = this.options.sortOrder || ( - _GET(`${_prefix}order`) ? _GET(`${_prefix}order`) : $.BootstrapTable.DEFAULTS.sortOrder - ) - this.options.sortName = this.options.sortName || ( - _GET(`${_prefix}sort`) ? _GET(`${_prefix}sort`) : 'id' - ) - this.options.searchText = this.options.searchText || ( - _GET(`${_prefix}search`) ? _GET(`${_prefix}search`) : $.BootstrapTable.DEFAULTS.searchText - ) + $__default['default'].BootstrapTable = /*#__PURE__*/function (_$$BootstrapTable) { + _inherits(_class, _$$BootstrapTable); - const _onLoadSuccess = this.options.onLoadSuccess + var _super = _createSuper(_class); - this.options.onLoadSuccess = data => { - if (this.addrbarInit) { - this.addrbarInit = false - } else { - const params = {} - params[`${_prefix}page`] = this.options.pageNumber, - params[`${_prefix}limit`] = this.options.pageSize, - params[`${_prefix}order`] = this.options.sortOrder, - params[`${_prefix}sort`] = this.options.sortName, - params[`${_prefix}search`] = this.options.searchText - // h5提供的修改浏览器地址栏的方法 - window.history.pushState({}, '', _buildUrl(params)) - } + function _class() { + _classCallCheck(this, _class); - if (_onLoadSuccess) { - _onLoadSuccess.call(this, data) - } + return _super.apply(this, arguments); + } + + _createClass(_class, [{ + key: "init", + value: function init() { + var _this = this, + _get2; + + if (this.options.pagination && this.options.addrbar) { + // 标志位, 初始加载后关闭 + this.addrbarInit = true; + this.options.pageNumber = +this.getDefaultOptionValue('pageNumber', 'page'); + this.options.pageSize = +this.getDefaultOptionValue('pageSize', 'size'); + this.options.sortOrder = this.getDefaultOptionValue('sortOrder', 'order'); + this.options.sortName = this.getDefaultOptionValue('sortName', 'sort'); + this.options.searchText = this.getDefaultOptionValue('searchText', 'search'); + + var _prefix = this.options.addrPrefix || ''; + + var _onLoadSuccess = this.options.onLoadSuccess; + var _onPageChange = this.options.onPageChange; + + this.options.onLoadSuccess = function (data) { + if (_this.addrbarInit) { + _this.addrbarInit = false; + } else { + _updateHistoryState(_this, _prefix); + } + + if (_onLoadSuccess) { + _onLoadSuccess.call(_this, data); + } + }; + + this.options.onPageChange = function (number, size) { + _updateHistoryState(_this, _prefix); + + if (_onPageChange) { + _onPageChange.call(_this, number, size); + } + }; } + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + (_get2 = _get(_getPrototypeOf(_class.prototype), "init", this)).call.apply(_get2, [this].concat(args)); } - super.init() - } - } -})(jQuery) + /* + * Priority order: + * The value specified by the user has the highest priority. + * If it is not specified, it will be obtained from the address bar. + * If it is not obtained, the default value will be used. + */ + + }, { + key: "getDefaultOptionValue", + value: function getDefaultOptionValue(optionName, prefixName) { + if (this.options[optionName] !== $__default['default'].BootstrapTable.DEFAULTS[optionName]) { + return this.options[optionName]; + } + + return _GET("".concat(this.options.addrPrefix || '').concat(prefixName)) || $__default['default'].BootstrapTable.DEFAULTS[optionName]; + } + }]); + + return _class; + }($__default['default'].BootstrapTable); + +}))); diff --git a/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.min.js b/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.min.js new file mode 100644 index 0000000000..9cc62f2749 --- /dev/null +++ b/InvenTree/InvenTree/static/bootstrap-table/extensions/addrbar/bootstrap-table-addrbar.min.js @@ -0,0 +1,10 @@ +/** + * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation) + * + * @version v1.18.3 + * @homepage https://bootstrap-table.com + * @author wenzhixin (http://wenzhixin.net.cn/) + * @license MIT + */ + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).jQuery)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t);function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){for(var n=0;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n0?vt:gt)(t)},bt=Math.min,xt=function(t){return t>0?bt(yt(t),9007199254740991):0},mt=Math.max,Et=Math.min,St=function(t){return function(e,n,r){var o,i=P(e),a=xt(i.length),c=function(t,e){var n=yt(t);return n<0?mt(n+e,0):Et(n,e)}(r,a);if(t&&n!=n){for(;a>c;)if((o=i[c++])!=o)return!0}else for(;a>c;c++)if((t||c in i)&&i[c]===n)return t||c||0;return!t&&-1}},Ot={includes:St(!0),indexOf:St(!1)}.indexOf,wt=function(t,e){var n,r=P(t),o=0,i=[];for(n in r)!A(rt,n)&&A(r,n)&&i.push(n);for(;e.length>o;)A(r,n=e[o++])&&(~Ot(i,n)||i.push(n));return i},jt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Rt=jt.concat("length","prototype"),Pt={f:Object.getOwnPropertyNames||function(t){return wt(t,Rt)}},Tt={f:Object.getOwnPropertySymbols},_t=dt("Reflect","ownKeys")||function(t){var e=Pt.f(k(t)),n=Tt.f;return n?e.concat(n(t)):e},It=function(t,e){for(var n=_t(e),r=L.f,o=$.f,i=0;i0&&(!i.multiline||i.multiline&&"\n"!==t[i.lastIndex-1])&&(u="(?: "+u+")",l=" "+l,f++),n=new RegExp("^(?:"+u+")",c)),Wt&&(n=new RegExp("^"+u+"$(?!\\s)",c)),Gt&&(e=i.lastIndex),r=Vt.call(a?n:i,l),a?r?(r.input=r.input.slice(f),r[0]=r[0].slice(f),r.index=i.lastIndex,i.lastIndex+=r[0].length):i.lastIndex=0:Gt&&r&&(i.lastIndex=i.global?r.index+r[0].length:e),Wt&&r&&r.length>1&&Kt.call(r[0],n,(function(){for(o=1;o=74)&&(Qt=Zt.match(/Chrome\/(\d+)/))&&(Ht=Qt[1]);var re=Ht&&+Ht,oe=!!Object.getOwnPropertySymbols&&!v((function(){return!Symbol.sham&&(Jt?38===re:re>37&&re<41)})),ie=oe&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,ae=J("wks"),ce=g.Symbol,ue=ie?ce:ce&&ce.withoutSetter||et,fe=function(t){return A(ae,t)&&(oe||"string"==typeof ae[t])||(oe&&A(ce,t)?ae[t]=ce[t]:ae[t]=ue("Symbol."+t)),ae[t]},le=fe("species"),se=!v((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")})),pe="$0"==="a".replace(/./,"$0"),he=fe("replace"),de=!!/./[he]&&""===/./[he]("a","$0"),ge=!v((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]})),ve=function(t,e,n,r){var o=fe(t),i=!v((function(){var e={};return e[o]=function(){return 7},7!=""[t](e)})),a=i&&!v((function(){var e=!1,n=/a/;return"split"===t&&((n={}).constructor={},n.constructor[le]=function(){return n},n.flags="",n[o]=/./[o]),n.exec=function(){return e=!0,null},n[o](""),!e}));if(!i||!a||"replace"===t&&(!se||!pe||de)||"split"===t&&!ge){var c=/./[o],u=n(o,""[t],(function(t,e,n,r,o){return e.exec===Xt?i&&!o?{done:!0,value:c.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:pe,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:de}),f=u[0],l=u[1];st(String.prototype,t,f),st(RegExp.prototype,o,2==e?function(t,e){return l.call(t,this,e)}:function(t){return l.call(t,this)})}r&&B(RegExp.prototype[o],"sham",!0)},ye=Object.is||function(t,e){return t===e?0!==t||1/t==1/e:t!=t&&e!=e},be=function(t,e){var n=t.exec;if("function"==typeof n){var r=n.call(t,e);if("object"!=typeof r)throw TypeError("RegExp exec method returned something other than an Object or null");return r}if("RegExp"!==O(t))throw TypeError("RegExp#exec called on incompatible receiver");return Xt.call(t,e)};ve("search",1,(function(t,e,n){return[function(e){var n=R(this),r=null==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var o=k(t),i=String(this),a=o.lastIndex;ye(a,0)||(o.lastIndex=0);var c=be(o,i);return ye(o.lastIndex,a)||(o.lastIndex=a),null===c?-1:c.index}]}));var xe=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{(t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(n,[]),e=n instanceof Array}catch(t){}return function(n,r){return k(n),function(t){if(!T(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype")}(r),e?t.call(n,r):n.__proto__=r,n}}():void 0),me=fe("match"),Ee=fe("species"),Se=L.f,Oe=Pt.f,we=lt.set,je=fe("match"),Re=g.RegExp,Pe=Re.prototype,Te=/a/g,_e=/a/g,Ie=new Re(Te)!==Te,Ae=zt.UNSUPPORTED_Y;if(y&&kt("RegExp",!Ie||Ae||v((function(){return _e[je]=!1,Re(Te)!=Te||Re(_e)==_e||"/a/i"!=Re(Te,"i")})))){for(var Ce=function(t,e){var n,r,o,i=this instanceof Ce,a=T(n=t)&&(void 0!==(r=n[me])?!!r:"RegExp"==O(n)),c=void 0===e;if(!i&&a&&t.constructor===Ce&&c)return t;Ie?a&&!c&&(t=t.source):t instanceof Ce&&(c&&(e=Bt.call(t)),t=t.source),Ae&&(o=!!e&&e.indexOf("y")>-1)&&(e=e.replace(/y/g,""));var u,f,l,s,p,h=(u=Ie?new Re(t,e):Re(t,e),f=i?this:Pe,l=Ce,xe&&"function"==typeof(s=f.constructor)&&s!==l&&T(p=s.prototype)&&p!==l.prototype&&xe(u,p),u);return Ae&&o&&we(h,{sticky:o}),h},De=function(t){t in Ce||Se(Ce,t,{configurable:!0,get:function(){return Re[t]},set:function(e){Re[t]=e}})},Ne=Oe(Re),Ue=0;Ne.length>Ue;)De(Ne[Ue++]);Pe.constructor=Ce,Ce.prototype=Pe,st(g,"RegExp",Ce)}!function(t){var e=dt(t),n=L.f;y&&e&&!e[Ee]&&n(e,Ee,{configurable:!0,get:function(){return this}})}("RegExp");var $e="toString",ke=RegExp.prototype,Me=ke.toString,Le=v((function(){return"/a/b"!=Me.call({source:"a",flags:"b"})})),Be=Me.name!=$e;(Le||Be)&&st(RegExp.prototype,$e,(function(){var t=k(this),e=String(t.source),n=t.flags;return"/"+e+"/"+String(void 0===n&&t instanceof RegExp&&!("flags"in ke)?Bt.call(t):n)}),{unsafe:!0});var Fe=function(t){return function(e,n){var r,o,i=String(R(e)),a=yt(n),c=i.length;return a<0||a>=c?t?"":void 0:(r=i.charCodeAt(a))<55296||r>56319||a+1===c||(o=i.charCodeAt(a+1))<56320||o>57343?t?i.charAt(a):r:t?i.slice(a,a+2):o-56320+(r-55296<<10)+65536}},ze={codeAt:Fe(!1),charAt:Fe(!0)}.charAt,Ve=function(t,e,n){return e+(n?ze(t,e).length:1)};ve("match",1,(function(t,e,n){return[function(e){var n=R(this),r=null==e?void 0:e[t];return void 0!==r?r.call(e,n):new RegExp(e)[t](String(n))},function(t){var r=n(e,t,this);if(r.done)return r.value;var o=k(t),i=String(this);if(!o.global)return be(o,i);var a=o.unicode;o.lastIndex=0;for(var c,u=[],f=0;null!==(c=be(o,i));){var l=String(c[0]);u[f]=l,""===l&&(o.lastIndex=Ve(i,xt(o.lastIndex),a)),f++}return 0===f?null:u}]}));var Ke=Object.keys||function(t){return wt(t,jt)},qe=m.f,Ge=function(t){return function(e){for(var n,r=P(e),o=Ke(r),i=o.length,a=0,c=[];i>a;)n=o[a++],y&&!qe.call(r,n)||c.push(t?[n,r[n]]:r[n]);return c}},Ye={entries:Ge(!0),values:Ge(!1)}.entries;Lt({target:"Object",stat:!0},{entries:function(t){return Ye(t)}});var We,Xe=Array.isArray||function(t){return"Array"==O(t)},Qe=function(t){return Object(R(t))},He=function(t,e,n){var r=_(e);r in t?L.f(t,r,E(0,n)):t[r]=n},Je=fe("species"),Ze=function(t,e){var n;return Xe(t)&&("function"!=typeof(n=t.constructor)||n!==Array&&!Xe(n.prototype)?T(n)&&null===(n=n[Je])&&(n=void 0):n=void 0),new(void 0===n?Array:n)(0===e?0:e)},tn=fe("species"),en=fe("isConcatSpreadable"),nn=9007199254740991,rn="Maximum allowed index exceeded",on=re>=51||!v((function(){var t=[];return t[en]=!1,t.concat()[0]!==t})),an=(We="concat",re>=51||!v((function(){var t=[];return(t.constructor={})[tn]=function(){return{foo:1}},1!==t[We](Boolean).foo}))),cn=function(t){if(!T(t))return!1;var e=t[en];return void 0!==e?!!e:Xe(t)};Lt({target:"Array",proto:!0,forced:!on||!an},{concat:function(t){var e,n,r,o,i,a=Qe(this),c=Ze(a,0),u=0;for(e=-1,r=arguments.length;enn)throw TypeError(rn);for(n=0;n=nn)throw TypeError(rn);He(c,u++,i)}return c.length=u,c}});var un=Math.floor,fn="".replace,ln=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,sn=/\$([$&'`]|\d{1,2})/g,pn=function(t,e,n,r,o,i){var a=n+t.length,c=r.length,u=sn;return void 0!==o&&(o=Qe(o),u=ln),fn.call(i,u,(function(i,u){var f;switch(u.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,n);case"'":return e.slice(a);case"<":f=o[u.slice(1,-1)];break;default:var l=+u;if(0===l)return i;if(l>c){var s=un(l/10);return 0===s?i:s<=c?void 0===r[s-1]?u.charAt(1):r[s-1]+u.charAt(1):i}f=r[l-1]}return void 0===f?"":f}))},hn=Math.max,dn=Math.min;function gn(t,e){var n={};n["".concat(e,"page")]=t.options.pageNumber,n["".concat(e,"size")]=t.options.pageSize,n["".concat(e,"order")]=t.options.sortOrder,n["".concat(e,"sort")]=t.options.sortName,n["".concat(e,"search")]=t.options.searchText,window.history.pushState({},"",function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window.location.search,n=0,r=Object.entries(t);n=y&&(v+=f.slice(y,m)+j,y=m+x.length)}return v+f.slice(y)}]})),n.default.extend(n.default.fn.bootstrapTable.defaults,{addrbar:!1,addrPrefix:""}),n.default.BootstrapTable=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&a(t,e)}(p,t);var e,c,l,s=u(p);function p(){return r(this,p),s.apply(this,arguments)}return e=p,(c=[{key:"init",value:function(){var t,e=this;if(this.options.pagination&&this.options.addrbar){this.addrbarInit=!0,this.options.pageNumber=+this.getDefaultOptionValue("pageNumber","page"),this.options.pageSize=+this.getDefaultOptionValue("pageSize","size"),this.options.sortOrder=this.getDefaultOptionValue("sortOrder","order"),this.options.sortName=this.getDefaultOptionValue("sortName","sort"),this.options.searchText=this.getDefaultOptionValue("searchText","search");var n=this.options.addrPrefix||"",r=this.options.onLoadSuccess,o=this.options.onPageChange;this.options.onLoadSuccess=function(t){e.addrbarInit?e.addrbarInit=!1:gn(e,n),r&&r.call(e,t)},this.options.onPageChange=function(t,r){gn(e,n),o&&o.call(e,t,r)}}for(var a=arguments.length,c=new Array(a),u=0;u1&&void 0!==arguments[1]?arguments[1]:window.location.search,n=new RegExp("(^|&)".concat(t,"=([^&]*)(&|$)")),r=e.substr(1).match(n);return r?decodeURIComponent(r[2]):null}("".concat(this.options.addrPrefix||"").concat(e))||n.default.BootstrapTable.DEFAULTS[t]}}])&&o(e.prototype,c),l&&o(e,l),p}(n.default.BootstrapTable)})); diff --git a/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js b/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js index 42edf633e9..287b4bd6b9 100644 --- a/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js +++ b/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.js @@ -1,78 +1,1211 @@ -/** - * @author: Alec Fenichel - * @webSite: https://fenichelar.com - * @update: zhixin wen - */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) : + typeof define === 'function' && define.amd ? define(['jquery'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jQuery)); +}(this, (function ($) { 'use strict'; -($ => { - const Utils = $.fn.bootstrapTable.utils + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - $.extend($.fn.bootstrapTable.defaults, { + var $__default = /*#__PURE__*/_interopDefaultLegacy($); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); + } + + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; + } + + function _superPropBase(object, property) { + while (!Object.prototype.hasOwnProperty.call(object, property)) { + object = _getPrototypeOf(object); + if (object === null) break; + } + + return object; + } + + function _get(target, property, receiver) { + if (typeof Reflect !== "undefined" && Reflect.get) { + _get = Reflect.get; + } else { + _get = function _get(target, property, receiver) { + var base = _superPropBase(target, property); + + if (!base) return; + var desc = Object.getOwnPropertyDescriptor(base, property); + + if (desc.get) { + return desc.get.call(receiver); + } + + return desc.value; + }; + } + + return _get(target, property, receiver || target); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var check = function (it) { + return it && it.Math == Math && it; + }; + + // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 + var global_1 = + /* global globalThis -- safe */ + check(typeof globalThis == 'object' && globalThis) || + check(typeof window == 'object' && window) || + check(typeof self == 'object' && self) || + check(typeof commonjsGlobal == 'object' && commonjsGlobal) || + // eslint-disable-next-line no-new-func -- fallback + (function () { return this; })() || Function('return this')(); + + var fails = function (exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + + // Detect IE8's incomplete defineProperty implementation + var descriptors = !fails(function () { + return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7; + }); + + var nativePropertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor; + + // Nashorn ~ JDK8 bug + var NASHORN_BUG = getOwnPropertyDescriptor$1 && !nativePropertyIsEnumerable.call({ 1: 2 }, 1); + + // `Object.prototype.propertyIsEnumerable` method implementation + // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable + var f$4 = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor$1(this, V); + return !!descriptor && descriptor.enumerable; + } : nativePropertyIsEnumerable; + + var objectPropertyIsEnumerable = { + f: f$4 + }; + + var createPropertyDescriptor = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; + }; + + var toString = {}.toString; + + var classofRaw = function (it) { + return toString.call(it).slice(8, -1); + }; + + var split = ''.split; + + // fallback for non-array-like ES3 and non-enumerable old V8 strings + var indexedObject = fails(function () { + // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346 + // eslint-disable-next-line no-prototype-builtins -- safe + return !Object('z').propertyIsEnumerable(0); + }) ? function (it) { + return classofRaw(it) == 'String' ? split.call(it, '') : Object(it); + } : Object; + + // `RequireObjectCoercible` abstract operation + // https://tc39.es/ecma262/#sec-requireobjectcoercible + var requireObjectCoercible = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; + }; + + // toObject with fallback for non-array-like ES3 strings + + + + var toIndexedObject = function (it) { + return indexedObject(requireObjectCoercible(it)); + }; + + var isObject = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; + }; + + // `ToPrimitive` abstract operation + // https://tc39.es/ecma262/#sec-toprimitive + // instead of the ES6 spec version, we didn't implement @@toPrimitive case + // and the second argument - flag - preferred type is a string + var toPrimitive = function (input, PREFERRED_STRING) { + if (!isObject(input)) return input; + var fn, val; + if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val; + if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val; + throw TypeError("Can't convert object to primitive value"); + }; + + var hasOwnProperty = {}.hasOwnProperty; + + var has$1 = function (it, key) { + return hasOwnProperty.call(it, key); + }; + + var document$1 = global_1.document; + // typeof document.createElement is 'object' in old IE + var EXISTS = isObject(document$1) && isObject(document$1.createElement); + + var documentCreateElement = function (it) { + return EXISTS ? document$1.createElement(it) : {}; + }; + + // Thank's IE8 for his funny defineProperty + var ie8DomDefine = !descriptors && !fails(function () { + return Object.defineProperty(documentCreateElement('div'), 'a', { + get: function () { return 7; } + }).a != 7; + }); + + var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + + // `Object.getOwnPropertyDescriptor` method + // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor + var f$3 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject(O); + P = toPrimitive(P, true); + if (ie8DomDefine) try { + return nativeGetOwnPropertyDescriptor(O, P); + } catch (error) { /* empty */ } + if (has$1(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]); + }; + + var objectGetOwnPropertyDescriptor = { + f: f$3 + }; + + var anObject = function (it) { + if (!isObject(it)) { + throw TypeError(String(it) + ' is not an object'); + } return it; + }; + + var nativeDefineProperty = Object.defineProperty; + + // `Object.defineProperty` method + // https://tc39.es/ecma262/#sec-object.defineproperty + var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (ie8DomDefine) try { + return nativeDefineProperty(O, P, Attributes); + } catch (error) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; + }; + + var objectDefineProperty = { + f: f$2 + }; + + var createNonEnumerableProperty = descriptors ? function (object, key, value) { + return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value)); + } : function (object, key, value) { + object[key] = value; + return object; + }; + + var setGlobal = function (key, value) { + try { + createNonEnumerableProperty(global_1, key, value); + } catch (error) { + global_1[key] = value; + } return value; + }; + + var SHARED = '__core-js_shared__'; + var store$1 = global_1[SHARED] || setGlobal(SHARED, {}); + + var sharedStore = store$1; + + var functionToString = Function.toString; + + // this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper + if (typeof sharedStore.inspectSource != 'function') { + sharedStore.inspectSource = function (it) { + return functionToString.call(it); + }; + } + + var inspectSource = sharedStore.inspectSource; + + var WeakMap$1 = global_1.WeakMap; + + var nativeWeakMap = typeof WeakMap$1 === 'function' && /native code/.test(inspectSource(WeakMap$1)); + + var shared = createCommonjsModule(function (module) { + (module.exports = function (key, value) { + return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); + })('versions', []).push({ + version: '3.9.1', + mode: 'global', + copyright: '© 2021 Denis Pushkarev (zloirock.ru)' + }); + }); + + var id = 0; + var postfix = Math.random(); + + var uid = function (key) { + return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36); + }; + + var keys = shared('keys'); + + var sharedKey = function (key) { + return keys[key] || (keys[key] = uid(key)); + }; + + var hiddenKeys$1 = {}; + + var WeakMap = global_1.WeakMap; + var set, get, has; + + var enforce = function (it) { + return has(it) ? get(it) : set(it, {}); + }; + + var getterFor = function (TYPE) { + return function (it) { + var state; + if (!isObject(it) || (state = get(it)).type !== TYPE) { + throw TypeError('Incompatible receiver, ' + TYPE + ' required'); + } return state; + }; + }; + + if (nativeWeakMap) { + var store = sharedStore.state || (sharedStore.state = new WeakMap()); + var wmget = store.get; + var wmhas = store.has; + var wmset = store.set; + set = function (it, metadata) { + metadata.facade = it; + wmset.call(store, it, metadata); + return metadata; + }; + get = function (it) { + return wmget.call(store, it) || {}; + }; + has = function (it) { + return wmhas.call(store, it); + }; + } else { + var STATE = sharedKey('state'); + hiddenKeys$1[STATE] = true; + set = function (it, metadata) { + metadata.facade = it; + createNonEnumerableProperty(it, STATE, metadata); + return metadata; + }; + get = function (it) { + return has$1(it, STATE) ? it[STATE] : {}; + }; + has = function (it) { + return has$1(it, STATE); + }; + } + + var internalState = { + set: set, + get: get, + has: has, + enforce: enforce, + getterFor: getterFor + }; + + var redefine = createCommonjsModule(function (module) { + var getInternalState = internalState.get; + var enforceInternalState = internalState.enforce; + var TEMPLATE = String(String).split('String'); + + (module.exports = function (O, key, value, options) { + var unsafe = options ? !!options.unsafe : false; + var simple = options ? !!options.enumerable : false; + var noTargetGet = options ? !!options.noTargetGet : false; + var state; + if (typeof value == 'function') { + if (typeof key == 'string' && !has$1(value, 'name')) { + createNonEnumerableProperty(value, 'name', key); + } + state = enforceInternalState(value); + if (!state.source) { + state.source = TEMPLATE.join(typeof key == 'string' ? key : ''); + } + } + if (O === global_1) { + if (simple) O[key] = value; + else setGlobal(key, value); + return; + } else if (!unsafe) { + delete O[key]; + } else if (!noTargetGet && O[key]) { + simple = true; + } + if (simple) O[key] = value; + else createNonEnumerableProperty(O, key, value); + // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative + })(Function.prototype, 'toString', function toString() { + return typeof this == 'function' && getInternalState(this).source || inspectSource(this); + }); + }); + + var path = global_1; + + var aFunction$1 = function (variable) { + return typeof variable == 'function' ? variable : undefined; + }; + + var getBuiltIn = function (namespace, method) { + return arguments.length < 2 ? aFunction$1(path[namespace]) || aFunction$1(global_1[namespace]) + : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; + }; + + var ceil = Math.ceil; + var floor = Math.floor; + + // `ToInteger` abstract operation + // https://tc39.es/ecma262/#sec-tointeger + var toInteger = function (argument) { + return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument); + }; + + var min$1 = Math.min; + + // `ToLength` abstract operation + // https://tc39.es/ecma262/#sec-tolength + var toLength = function (argument) { + return argument > 0 ? min$1(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991 + }; + + var max = Math.max; + var min = Math.min; + + // Helper for a popular repeating case of the spec: + // Let integer be ? ToInteger(index). + // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length). + var toAbsoluteIndex = function (index, length) { + var integer = toInteger(index); + return integer < 0 ? max(integer + length, 0) : min(integer, length); + }; + + // `Array.prototype.{ indexOf, includes }` methods implementation + var createMethod$1 = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare -- NaN check + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare -- NaN check + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; + }; + + var arrayIncludes = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod$1(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod$1(false) + }; + + var indexOf = arrayIncludes.indexOf; + + + var objectKeysInternal = function (object, names) { + var O = toIndexedObject(object); + var i = 0; + var result = []; + var key; + for (key in O) !has$1(hiddenKeys$1, key) && has$1(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has$1(O, key = names[i++])) { + ~indexOf(result, key) || result.push(key); + } + return result; + }; + + // IE8- don't enum bug keys + var enumBugKeys = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + var hiddenKeys = enumBugKeys.concat('length', 'prototype'); + + // `Object.getOwnPropertyNames` method + // https://tc39.es/ecma262/#sec-object.getownpropertynames + var f$1 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return objectKeysInternal(O, hiddenKeys); + }; + + var objectGetOwnPropertyNames = { + f: f$1 + }; + + var f = Object.getOwnPropertySymbols; + + var objectGetOwnPropertySymbols = { + f: f + }; + + // all object keys, includes non-enumerable and symbols + var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) { + var keys = objectGetOwnPropertyNames.f(anObject(it)); + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys; + }; + + var copyConstructorProperties = function (target, source) { + var keys = ownKeys(source); + var defineProperty = objectDefineProperty.f; + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!has$1(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + }; + + var replacement = /#|\.prototype\./; + + var isForced = function (feature, detection) { + var value = data[normalize(feature)]; + return value == POLYFILL ? true + : value == NATIVE ? false + : typeof detection == 'function' ? fails(detection) + : !!detection; + }; + + var normalize = isForced.normalize = function (string) { + return String(string).replace(replacement, '.').toLowerCase(); + }; + + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = 'N'; + var POLYFILL = isForced.POLYFILL = 'P'; + + var isForced_1 = isForced; + + var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f; + + + + + + + /* + options.target - name of the target object + options.global - target is the global object + options.stat - export as static methods of target + options.proto - export as prototype methods of target + options.real - real prototype method for the `pure` version + options.forced - export even if the native feature is available + options.bind - bind methods to the target, required for the `pure` version + options.wrap - wrap constructors to preventing global pollution, required for the `pure` version + options.unsafe - use the simple assignment of property instead of delete + defineProperty + options.sham - add a flag to not completely full polyfills + options.enumerable - export as enumerable property + options.noTargetGet - prevent calling a getter on target + */ + var _export = function (options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = global_1; + } else if (STATIC) { + target = global_1[TARGET] || setGlobal(TARGET, {}); + } else { + target = (global_1[TARGET] || {}).prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.noTargetGet) { + descriptor = getOwnPropertyDescriptor(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced); + // contained in target + if (!FORCED && targetProperty !== undefined) { + if (typeof sourceProperty === typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + // add a flag to not completely full polyfills + if (options.sham || (targetProperty && targetProperty.sham)) { + createNonEnumerableProperty(sourceProperty, 'sham', true); + } + // extend global + redefine(target, key, sourceProperty, options); + } + }; + + // `IsArray` abstract operation + // https://tc39.es/ecma262/#sec-isarray + var isArray = Array.isArray || function isArray(arg) { + return classofRaw(arg) == 'Array'; + }; + + // `ToObject` abstract operation + // https://tc39.es/ecma262/#sec-toobject + var toObject = function (argument) { + return Object(requireObjectCoercible(argument)); + }; + + var createProperty = function (object, key, value) { + var propertyKey = toPrimitive(key); + if (propertyKey in object) objectDefineProperty.f(object, propertyKey, createPropertyDescriptor(0, value)); + else object[propertyKey] = value; + }; + + var engineIsNode = classofRaw(global_1.process) == 'process'; + + var engineUserAgent = getBuiltIn('navigator', 'userAgent') || ''; + + var process = global_1.process; + var versions = process && process.versions; + var v8 = versions && versions.v8; + var match, version; + + if (v8) { + match = v8.split('.'); + version = match[0] + match[1]; + } else if (engineUserAgent) { + match = engineUserAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = engineUserAgent.match(/Chrome\/(\d+)/); + if (match) version = match[1]; + } + } + + var engineV8Version = version && +version; + + var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () { + /* global Symbol -- required for testing */ + return !Symbol.sham && + // Chrome 38 Symbol has incorrect toString conversion + // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + (engineIsNode ? engineV8Version === 38 : engineV8Version > 37 && engineV8Version < 41); + }); + + var useSymbolAsUid = nativeSymbol + /* global Symbol -- safe */ + && !Symbol.sham + && typeof Symbol.iterator == 'symbol'; + + var WellKnownSymbolsStore = shared('wks'); + var Symbol$1 = global_1.Symbol; + var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; + + var wellKnownSymbol = function (name) { + if (!has$1(WellKnownSymbolsStore, name) || !(nativeSymbol || typeof WellKnownSymbolsStore[name] == 'string')) { + if (nativeSymbol && has$1(Symbol$1, name)) { + WellKnownSymbolsStore[name] = Symbol$1[name]; + } else { + WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name); + } + } return WellKnownSymbolsStore[name]; + }; + + var SPECIES$1 = wellKnownSymbol('species'); + + // `ArraySpeciesCreate` abstract operation + // https://tc39.es/ecma262/#sec-arrayspeciescreate + var arraySpeciesCreate = function (originalArray, length) { + var C; + if (isArray(originalArray)) { + C = originalArray.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; + else if (isObject(C)) { + C = C[SPECIES$1]; + if (C === null) C = undefined; + } + } return new (C === undefined ? Array : C)(length === 0 ? 0 : length); + }; + + var SPECIES = wellKnownSymbol('species'); + + var arrayMethodHasSpeciesSupport = function (METHOD_NAME) { + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/677 + return engineV8Version >= 51 || !fails(function () { + var array = []; + var constructor = array.constructor = {}; + constructor[SPECIES] = function () { + return { foo: 1 }; + }; + return array[METHOD_NAME](Boolean).foo !== 1; + }); + }; + + var IS_CONCAT_SPREADABLE = wellKnownSymbol('isConcatSpreadable'); + var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; + var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded'; + + // We can't use this feature detection in V8 since it causes + // deoptimization and serious performance degradation + // https://github.com/zloirock/core-js/issues/679 + var IS_CONCAT_SPREADABLE_SUPPORT = engineV8Version >= 51 || !fails(function () { + var array = []; + array[IS_CONCAT_SPREADABLE] = false; + return array.concat()[0] !== array; + }); + + var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('concat'); + + var isConcatSpreadable = function (O) { + if (!isObject(O)) return false; + var spreadable = O[IS_CONCAT_SPREADABLE]; + return spreadable !== undefined ? !!spreadable : isArray(O); + }; + + var FORCED = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT; + + // `Array.prototype.concat` method + // https://tc39.es/ecma262/#sec-array.prototype.concat + // with adding support of @@isConcatSpreadable and @@species + _export({ target: 'Array', proto: true, forced: FORCED }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + concat: function concat(arg) { + var O = toObject(this); + var A = arraySpeciesCreate(O, 0); + var n = 0; + var i, k, length, len, E; + for (i = -1, length = arguments.length; i < length; i++) { + E = i === -1 ? O : arguments[i]; + if (isConcatSpreadable(E)) { + len = toLength(E.length); + if (n + len > MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + for (k = 0; k < len; k++, n++) if (k in E) createProperty(A, n, E[k]); + } else { + if (n >= MAX_SAFE_INTEGER) throw TypeError(MAXIMUM_ALLOWED_INDEX_EXCEEDED); + createProperty(A, n++, E); + } + } + A.length = n; + return A; + } + }); + + // `Object.keys` method + // https://tc39.es/ecma262/#sec-object.keys + var objectKeys = Object.keys || function keys(O) { + return objectKeysInternal(O, enumBugKeys); + }; + + var nativeAssign = Object.assign; + var defineProperty = Object.defineProperty; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + var objectAssign = !nativeAssign || fails(function () { + // should have correct order of operations (Edge bug) + if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty({}, 'a', { + enumerable: true, + get: function () { + defineProperty(this, 'b', { + value: 3, + enumerable: false + }); + } + }), { b: 2 })).b !== 1) return true; + // should work with symbols and should have deterministic property order (V8 bug) + var A = {}; + var B = {}; + /* global Symbol -- required for testing */ + var symbol = Symbol(); + var alphabet = 'abcdefghijklmnopqrst'; + A[symbol] = 7; + alphabet.split('').forEach(function (chr) { B[chr] = chr; }); + return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet; + }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length` + var T = toObject(target); + var argumentsLength = arguments.length; + var index = 1; + var getOwnPropertySymbols = objectGetOwnPropertySymbols.f; + var propertyIsEnumerable = objectPropertyIsEnumerable.f; + while (argumentsLength > index) { + var S = indexedObject(arguments[index++]); + var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) { + key = keys[j++]; + if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key]; + } + } return T; + } : nativeAssign; + + // `Object.assign` method + // https://tc39.es/ecma262/#sec-object.assign + _export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, { + assign: objectAssign + }); + + var aFunction = function (it) { + if (typeof it != 'function') { + throw TypeError(String(it) + ' is not a function'); + } return it; + }; + + // optional / simple context binding + var functionBindContext = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 0: return function () { + return fn.call(that); + }; + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; + }; + + var push = [].push; + + // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterOut }` methods implementation + var createMethod = function (TYPE) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var IS_FILTER_OUT = TYPE == 7; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + return function ($this, callbackfn, that, specificCreate) { + var O = toObject($this); + var self = indexedObject(O); + var boundFunction = functionBindContext(callbackfn, that, 3); + var length = toLength(self.length); + var index = 0; + var create = specificCreate || arraySpeciesCreate; + var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_OUT ? create($this, 0) : undefined; + var value, result; + for (;length > index; index++) if (NO_HOLES || index in self) { + value = self[index]; + result = boundFunction(value, index, O); + if (TYPE) { + if (IS_MAP) target[index] = result; // map + else if (result) switch (TYPE) { + case 3: return true; // some + case 5: return value; // find + case 6: return index; // findIndex + case 2: push.call(target, value); // filter + } else switch (TYPE) { + case 4: return false; // every + case 7: push.call(target, value); // filterOut + } + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target; + }; + }; + + var arrayIteration = { + // `Array.prototype.forEach` method + // https://tc39.es/ecma262/#sec-array.prototype.foreach + forEach: createMethod(0), + // `Array.prototype.map` method + // https://tc39.es/ecma262/#sec-array.prototype.map + map: createMethod(1), + // `Array.prototype.filter` method + // https://tc39.es/ecma262/#sec-array.prototype.filter + filter: createMethod(2), + // `Array.prototype.some` method + // https://tc39.es/ecma262/#sec-array.prototype.some + some: createMethod(3), + // `Array.prototype.every` method + // https://tc39.es/ecma262/#sec-array.prototype.every + every: createMethod(4), + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + find: createMethod(5), + // `Array.prototype.findIndex` method + // https://tc39.es/ecma262/#sec-array.prototype.findIndex + findIndex: createMethod(6), + // `Array.prototype.filterOut` method + // https://github.com/tc39/proposal-array-filtering + filterOut: createMethod(7) + }; + + // `Object.defineProperties` method + // https://tc39.es/ecma262/#sec-object.defineproperties + var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = objectKeys(Properties); + var length = keys.length; + var index = 0; + var key; + while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]); + return O; + }; + + var html = getBuiltIn('document', 'documentElement'); + + var GT = '>'; + var LT = '<'; + var PROTOTYPE = 'prototype'; + var SCRIPT = 'script'; + var IE_PROTO = sharedKey('IE_PROTO'); + + var EmptyConstructor = function () { /* empty */ }; + + var scriptTag = function (content) { + return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT; + }; + + // Create object with fake `null` prototype: use ActiveX Object with cleared prototype + var NullProtoObjectViaActiveX = function (activeXDocument) { + activeXDocument.write(scriptTag('')); + activeXDocument.close(); + var temp = activeXDocument.parentWindow.Object; + activeXDocument = null; // avoid memory leak + return temp; + }; + + // Create object with fake `null` prototype: use iframe Object with cleared prototype + var NullProtoObjectViaIFrame = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = documentCreateElement('iframe'); + var JS = 'java' + SCRIPT + ':'; + var iframeDocument; + iframe.style.display = 'none'; + html.appendChild(iframe); + // https://github.com/zloirock/core-js/issues/475 + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag('document.F=Object')); + iframeDocument.close(); + return iframeDocument.F; + }; + + // Check for document.domain and active x support + // No need to use active x approach when document.domain is not set + // see https://github.com/es-shims/es5-shim/issues/150 + // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346 + // avoid IE GC bug + var activeXDocument; + var NullProtoObject = function () { + try { + /* global ActiveXObject -- old IE */ + activeXDocument = document.domain && new ActiveXObject('htmlfile'); + } catch (error) { /* ignore */ } + NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame(); + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]]; + return NullProtoObject(); + }; + + hiddenKeys$1[IE_PROTO] = true; + + // `Object.create` method + // https://tc39.es/ecma262/#sec-object.create + var objectCreate = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + EmptyConstructor[PROTOTYPE] = anObject(O); + result = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = NullProtoObject(); + return Properties === undefined ? result : objectDefineProperties(result, Properties); + }; + + var UNSCOPABLES = wellKnownSymbol('unscopables'); + var ArrayPrototype = Array.prototype; + + // Array.prototype[@@unscopables] + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + if (ArrayPrototype[UNSCOPABLES] == undefined) { + objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, { + configurable: true, + value: objectCreate(null) + }); + } + + // add a key to Array.prototype[@@unscopables] + var addToUnscopables = function (key) { + ArrayPrototype[UNSCOPABLES][key] = true; + }; + + var $find = arrayIteration.find; + + + var FIND = 'find'; + var SKIPS_HOLES = true; + + // Shouldn't skip holes + if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; }); + + // `Array.prototype.find` method + // https://tc39.es/ecma262/#sec-array.prototype.find + _export({ target: 'Array', proto: true, forced: SKIPS_HOLES }, { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } + }); + + // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables + addToUnscopables(FIND); + + /** + * @author: Alec Fenichel + * @webSite: https://fenichelar.com + * @update: zhixin wen + */ + + var Utils = $__default['default'].fn.bootstrapTable.utils; + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, { autoRefresh: false, autoRefreshInterval: 60, autoRefreshSilent: true, autoRefreshStatus: true, autoRefreshFunction: null - }) - - $.extend($.fn.bootstrapTable.defaults.icons, { - autoRefresh: Utils.bootstrapVersion === 4 ? 'fa-clock' : 'glyphicon-time icon-time' - }) - - $.extend($.fn.bootstrapTable.locales, { - formatAutoRefresh () { - return 'Auto Refresh' + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults.icons, { + autoRefresh: { + bootstrap3: 'glyphicon-time icon-time', + materialize: 'access_time', + 'bootstrap-table': 'icon-clock' + }[$__default['default'].fn.bootstrapTable.theme] || 'fa-clock' + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.locales, { + formatAutoRefresh: function formatAutoRefresh() { + return 'Auto Refresh'; } - }) + }); + $__default['default'].extend($__default['default'].fn.bootstrapTable.defaults, $__default['default'].fn.bootstrapTable.locales); - $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales) + $__default['default'].BootstrapTable = /*#__PURE__*/function (_$$BootstrapTable) { + _inherits(_class, _$$BootstrapTable); - $.BootstrapTable = class extends $.BootstrapTable { - init (...args) { - super.init(...args) + var _super = _createSuper(_class); - if (this.options.autoRefresh && this.options.autoRefreshStatus) { - this.options.autoRefreshFunction = setInterval(() => { - this.refresh({silent: this.options.autoRefreshSilent}) - }, this.options.autoRefreshInterval * 1000) - } + function _class() { + _classCallCheck(this, _class); + + return _super.apply(this, arguments); } - initToolbar (...args) { - super.initToolbar(...args) + _createClass(_class, [{ + key: "init", + value: function init() { + var _get2; - if (this.options.autoRefresh) { - const $btnGroup = this.$toolbar.find('>.btn-group') - let $btnAutoRefresh = $btnGroup.find('.auto-refresh') + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - if (!$btnAutoRefresh.length) { - $btnAutoRefresh = $(` - - `).appendTo($btnGroup) + (_get2 = _get(_getPrototypeOf(_class.prototype), "init", this)).call.apply(_get2, [this].concat(args)); - $btnAutoRefresh.on('click', $.proxy(this.toggleAutoRefresh, this)) + if (this.options.autoRefresh && this.options.autoRefreshStatus) { + this.setupRefreshInterval(); } } - } + }, { + key: "initToolbar", + value: function initToolbar() { + var _get3; - toggleAutoRefresh () { - if (this.options.autoRefresh) { - if (this.options.autoRefreshStatus) { - clearInterval(this.options.autoRefreshFunction) - this.$toolbar.find('>.btn-group').find('.auto-refresh').removeClass('active') - } else { - this.options.autoRefreshFunction = setInterval(() => { - this.refresh({silent: this.options.autoRefreshSilent}) - }, this.options.autoRefreshInterval * 1000) - this.$toolbar.find('>.btn-group').find('.auto-refresh').addClass('active') + if (this.options.autoRefresh) { + this.buttons = Object.assign(this.buttons, { + autoRefresh: { + html: "\n \n "), + event: this.toggleAutoRefresh + } + }); } - this.options.autoRefreshStatus = !this.options.autoRefreshStatus + + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + (_get3 = _get(_getPrototypeOf(_class.prototype), "initToolbar", this)).call.apply(_get3, [this].concat(args)); } - } - } -})(jQuery) + }, { + key: "toggleAutoRefresh", + value: function toggleAutoRefresh() { + if (this.options.autoRefresh) { + if (this.options.autoRefreshStatus) { + clearInterval(this.options.autoRefreshFunction); + this.$toolbar.find('>.columns .auto-refresh').removeClass(this.constants.classes.buttonActive); + } else { + this.setupRefreshInterval(); + this.$toolbar.find('>.columns .auto-refresh').addClass(this.constants.classes.buttonActive); + } + + this.options.autoRefreshStatus = !this.options.autoRefreshStatus; + } + } + }, { + key: "destroy", + value: function destroy() { + if (this.options.autoRefresh && this.options.autoRefreshStatus) { + clearInterval(this.options.autoRefreshFunction); + } + + _get(_getPrototypeOf(_class.prototype), "destroy", this).call(this); + } + }, { + key: "setupRefreshInterval", + value: function setupRefreshInterval() { + var _this = this; + + this.options.autoRefreshFunction = setInterval(function () { + if (!_this.options.autoRefresh || !_this.options.autoRefreshStatus) { + return; + } + + _this.refresh({ + silent: _this.options.autoRefreshSilent + }); + }, this.options.autoRefreshInterval * 1000); + } + }]); + + return _class; + }($__default['default'].BootstrapTable); + +}))); diff --git a/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js b/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js new file mode 100644 index 0000000000..6f73d42111 --- /dev/null +++ b/InvenTree/InvenTree/static/bootstrap-table/extensions/auto-refresh/bootstrap-table-auto-refresh.min.js @@ -0,0 +1,10 @@ +/** + * bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation) + * + * @version v1.18.3 + * @homepage https://bootstrap-table.com + * @author wenzhixin (http://wenzhixin.net.cn/) + * @license MIT + */ + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).jQuery)}(this,(function(t){"use strict";function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t);function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){for(var n=0;n0?vt:bt)(t)},mt=Math.min,wt=function(t){return t>0?mt(gt(t),9007199254740991):0},Ot=Math.max,jt=Math.min,Rt=function(t){return function(e,n,r){var o,i=T(e),u=wt(i.length),c=function(t,e){var n=gt(t);return n<0?Ot(n+e,0):jt(n,e)}(r,u);if(t&&n!=n){for(;u>c;)if((o=i[c++])!=o)return!0}else for(;u>c;c++)if((t||c in i)&&i[c]===n)return t||c||0;return!t&&-1}},St={includes:Rt(!0),indexOf:Rt(!1)}.indexOf,Tt=function(t,e){var n,r=T(t),o=0,i=[];for(n in r)!x(nt,n)&&x(r,n)&&i.push(n);for(;e.length>o;)x(r,n=e[o++])&&(~St(i,n)||i.push(n));return i},Pt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],At=Pt.concat("length","prototype"),Et={f:Object.getOwnPropertyNames||function(t){return Tt(t,At)}},xt={f:Object.getOwnPropertySymbols},It=dt("Reflect","ownKeys")||function(t){var e=Et.f(B(t)),n=xt.f;return n?e.concat(n(t)):e},kt=function(t,e){for(var n=It(e),r=L.f,o=C.f,i=0;i=74)&&(ft=Kt.match(/Chrome\/(\d+)/))&&(st=ft[1]);var Yt,Ht=st&&+st,Jt=!!Object.getOwnPropertySymbols&&!y((function(){return!Symbol.sham&&($t?38===Ht:Ht>37&&Ht<41)})),Ut=Jt&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,Zt=H("wks"),te=h.Symbol,ee=Ut?te:te&&te.withoutSetter||Z,ne=function(t){return x(Zt,t)&&(Jt||"string"==typeof Zt[t])||(Jt&&x(te,t)?Zt[t]=te[t]:Zt[t]=ee("Symbol."+t)),Zt[t]},re=ne("species"),oe=function(t,e){var n;return Dt(t)&&("function"!=typeof(n=t.constructor)||n!==Array&&!Dt(n.prototype)?P(n)&&null===(n=n[re])&&(n=void 0):n=void 0),new(void 0===n?Array:n)(0===e?0:e)},ie=ne("species"),ue=ne("isConcatSpreadable"),ce=9007199254740991,ae="Maximum allowed index exceeded",fe=Ht>=51||!y((function(){var t=[];return t[ue]=!1,t.concat()[0]!==t})),se=(Yt="concat",Ht>=51||!y((function(){var t=[];return(t.constructor={})[ie]=function(){return{foo:1}},1!==t[Yt](Boolean).foo}))),le=function(t){if(!P(t))return!1;var e=t[ue];return void 0!==e?!!e:Dt(t)};zt({target:"Array",proto:!0,forced:!fe||!se},{concat:function(t){var e,n,r,o,i,u=Wt(this),c=oe(u,0),a=0;for(e=-1,r=arguments.length;ece)throw TypeError(ae);for(n=0;n=ce)throw TypeError(ae);Gt(c,a++,i)}return c.length=a,c}});var pe=Object.keys||function(t){return Tt(t,Pt)},he=Object.assign,ye=Object.defineProperty,de=!he||y((function(){if(d&&1!==he({b:1},he(ye({},"a",{enumerable:!0,get:function(){ye(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},n=Symbol(),r="abcdefghijklmnopqrst";return t[n]=7,r.split("").forEach((function(t){e[t]=t})),7!=he({},t)[n]||pe(he({},e)).join("")!=r}))?function(t,e){for(var n=Wt(t),r=arguments.length,o=1,i=xt.f,u=g.f;r>o;)for(var c,a=R(arguments[o++]),f=i?pe(a).concat(i(a)):pe(a),s=f.length,l=0;s>l;)c=f[l++],d&&!u.call(a,c)||(n[c]=a[c]);return n}:he;zt({target:"Object",stat:!0,forced:Object.assign!==de},{assign:de});var be,ve=function(t,e,n){if(function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function")}(t),void 0===e)return t;switch(n){case 0:return function(){return t.call(e)};case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}},ge=[].push,me=function(t){var e=1==t,n=2==t,r=3==t,o=4==t,i=6==t,u=7==t,c=5==t||i;return function(a,f,s,l){for(var p,h,y=Wt(a),d=R(y),b=ve(f,s,3),v=wt(d.length),g=0,m=l||oe,w=e?m(a,v):n||u?m(a,0):void 0;v>g;g++)if((c||g in d)&&(h=b(p=d[g],g,y),t))if(e)w[g]=h;else if(h)switch(t){case 3:return!0;case 5:return p;case 6:return g;case 2:ge.call(w,p)}else switch(t){case 4:return!1;case 7:ge.call(w,p)}return i?-1:r||o?o:w}},we={forEach:me(0),map:me(1),filter:me(2),some:me(3),every:me(4),find:me(5),findIndex:me(6),filterOut:me(7)},Oe=d?Object.defineProperties:function(t,e){B(t);for(var n,r=pe(e),o=r.length,i=0;o>i;)L.f(t,n=r[i++],e[n]);return t},je=dt("document","documentElement"),Re=et("IE_PROTO"),Se=function(){},Te=function(t){return" - - - - + + + + diff --git a/InvenTree/templates/registration/logged_out.html b/InvenTree/templates/registration/logged_out.html index f5882c7ff1..e26ae16c60 100644 --- a/InvenTree/templates/registration/logged_out.html +++ b/InvenTree/templates/registration/logged_out.html @@ -14,7 +14,6 @@ - diff --git a/InvenTree/templates/registration/login.html b/InvenTree/templates/registration/login.html index 3b59dde2fc..aa398cac60 100644 --- a/InvenTree/templates/registration/login.html +++ b/InvenTree/templates/registration/login.html @@ -13,7 +13,6 @@ - diff --git a/InvenTree/templates/registration/password_reset_complete.html b/InvenTree/templates/registration/password_reset_complete.html index a941aa6fee..2254e966c8 100644 --- a/InvenTree/templates/registration/password_reset_complete.html +++ b/InvenTree/templates/registration/password_reset_complete.html @@ -14,7 +14,6 @@ - diff --git a/InvenTree/templates/registration/password_reset_confirm.html b/InvenTree/templates/registration/password_reset_confirm.html index dd52cb135f..a1f6d7d258 100644 --- a/InvenTree/templates/registration/password_reset_confirm.html +++ b/InvenTree/templates/registration/password_reset_confirm.html @@ -14,7 +14,6 @@ - diff --git a/InvenTree/templates/registration/password_reset_done.html b/InvenTree/templates/registration/password_reset_done.html index 03d98846a0..044dd3d30b 100644 --- a/InvenTree/templates/registration/password_reset_done.html +++ b/InvenTree/templates/registration/password_reset_done.html @@ -14,7 +14,6 @@ - diff --git a/InvenTree/templates/registration/password_reset_form.html b/InvenTree/templates/registration/password_reset_form.html index a2c241b7d7..f221e6a11b 100644 --- a/InvenTree/templates/registration/password_reset_form.html +++ b/InvenTree/templates/registration/password_reset_form.html @@ -14,7 +14,6 @@ - From f0cf83a0b80649fac88b162660ae4c99f175c84d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 31 May 2021 16:55:21 +1000 Subject: [PATCH 255/300] Use tree-grid instead of group-by for showing test results - Much more predictable display --- InvenTree/templates/js/stock.js | 124 ++++++++++++++++---------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index b89cceea83..da653402af 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -32,17 +32,32 @@ function removeStockRow(e) { } -function passFailBadge(result) { +function passFailBadge(result, align='float-right') { if (result) { - return `{% trans "PASS" %}`; + return `{% trans "PASS" %}`; } else { - return `{% trans "FAIL" %}`; + return `{% trans "FAIL" %}`; } } -function noResultBadge() { - return `{% trans "NO RESULT" %}`; +function noResultBadge(align='float-right') { + return `{% trans "NO RESULT" %}`; +} + +function formatDate(row) { + // Function for formatting date field + var html = row.date; + + if (row.user_detail) { + html += `${row.user_detail.username}`; + } + + if (row.attachment) { + html += ``; + } + + return html; } function loadStockTestResultsTable(table, options) { @@ -50,21 +65,6 @@ function loadStockTestResultsTable(table, options) { * Load StockItemTestResult table */ - function formatDate(row) { - // Function for formatting date field - var html = row.date; - - if (row.user_detail) { - html += `${row.user_detail.username}`; - } - - if (row.attachment) { - html += ``; - } - - return html; - } - function makeButtons(row, grouped) { var html = `
    `; @@ -81,17 +81,28 @@ function loadStockTestResultsTable(table, options) { return html; } - // First, load all the test templates table.inventreeTable({ url: "{% url 'api-part-test-template-list' %}", method: 'get', name: 'testresult', + treeEnable: true, + rootParentId: options.stock_item, + parentIdField: 'parent', + idField: 'pk', + uniqueId: 'pk', + treeShowField: 'test_name', formatNoMatches: function() { - return "{% trans 'No test results found' %}"; + return '{% trans "No test results found" %}'; }, queryParams: { part: options.part, }, + onPostBody: function() { + table.treegrid({ + treeColumn: 0, + }); + table.treegrid("collapseAll"); + }, columns: [ { field: 'pk', @@ -130,100 +141,85 @@ function loadStockTestResultsTable(table, options) { { field: 'date', title: '{% trans "Test Date" %}', + sortable: true, formatter: function(value, row) { return formatDate(row); - } + }, }, { field: 'buttons', formatter: function(value, row) { return makeButtons(row, false); } - }, - ], - groupBy: true, - groupByField: 'test_name', - groupByFormatter: function(field, id, data) { - - // Extract the "latest" row (data are returned in date order from the server) - var latest = data[data.length-1]; - - switch (field) { - case 'test_name': - return latest.test_name + ` (${data.length})` + passFailBadge(latest.result); - case 'value': - return latest.value; - case 'notes': - return latest.notes; - case 'date': - return formatDate(latest); - case 'buttons': - // Buttons are done differently for grouped rows - return makeButtons(latest, true); - default: - return "---"; } - }, + ], onLoadSuccess: function(tableData) { - // Once the test template data are loaded, query for results + + // Set "parent" for each existing row + tableData.forEach(function(item, idx) { + tableData[idx].parent = options.stock_item; + }); + + // Once the test template data are loaded, query for test results inventreeGet( - "{% url 'api-stock-test-result-list' %}", + '{% url "api-stock-test-result-list" %}', { stock_item: options.stock_item, user_detail: true, attachment_detail: true, + ordering: "-date", }, { success: function(data) { + // Iterate through the returned test data + data.forEach(function(item, index) { - // Iterate through the returned test result data, and group by test - data.forEach(function(item) { var match = false; var override = false; var key = item.key; - // Try to associate this result with a test row + // Attempt to associate this result with an existing test tableData.forEach(function(row, index) { - - // The result matches the test template row if (key == row.key) { - // Force the names to be the same! item.test_name = row.test_name; item.required = row.required; + match = true; + if (row.result == null) { - // The original row has not recorded a result - override! + item.parent = options.stock_item; tableData[index] = item; override = true; + } else { + item.parent = row.pk; } - - match = true; } }); - // No match could be found (this is a new test!) + // No match could be found if (!match) { - item.test_name = item.test; + item.parent = options.stock_item; } if (!override) { tableData.push(item); } + }); - // Finally, push the data back into the table! + // Push data back into the table table.bootstrapTable("load", tableData); } - }, - ); + } + ) } }); -} +} function loadStockTable(table, options) { /* Load data into a stock table with adjustable options. From 3ba7b2d136cb6052c5f8fa1b96ea44e6ddbf6988 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 31 May 2021 17:05:12 +1000 Subject: [PATCH 256/300] Visual hack for custom part card view --- InvenTree/templates/js/part.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index 5c2840b121..81cc4e0630 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -516,11 +516,21 @@ function loadPartTable(table, url, options={}) { var html = ''; - data.forEach(function(row) { + html = `
    `; + + data.forEach(function(row, index) { + + // Force a new row every 4 columns, to prevent visual issues + if ((index > 0) && (index % 4 == 0) && (index < data.length)) { + html += `
    `; + } + html += partGridTile(row); }); - return `
    ${html}
    `; + html += `
    `; + + return html; } }); From 0375d5b940f5a87f113270abe388bd76eb263cee Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 08:30:50 +1000 Subject: [PATCH 257/300] Specify a unique parent node that cannot shadow an existing pk --- InvenTree/templates/js/stock.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index da653402af..1a052b5fa1 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -81,15 +81,17 @@ function loadStockTestResultsTable(table, options) { return html; } + var parent_node = "parent node"; + table.inventreeTable({ url: "{% url 'api-part-test-template-list' %}", method: 'get', name: 'testresult', treeEnable: true, - rootParentId: options.stock_item, + rootParentId: parent_node, parentIdField: 'parent', idField: 'pk', - uniqueId: 'pk', + uniqueId: 'key', treeShowField: 'test_name', formatNoMatches: function() { return '{% trans "No test results found" %}'; @@ -190,7 +192,7 @@ function loadStockTestResultsTable(table, options) { match = true; if (row.result == null) { - item.parent = options.stock_item; + item.parent = parent_node; tableData[index] = item; override = true; } else { @@ -202,7 +204,7 @@ function loadStockTestResultsTable(table, options) { // No match could be found if (!match) { item.test_name = item.test; - item.parent = options.stock_item; + item.parent = parent_node; } if (!override) { From 5c71f04360f1779042e43509aa96c43efd984aca Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 13:59:01 +1000 Subject: [PATCH 258/300] Add "allow_variants" field to BomItem --- .../migrations/0066_bomitem_allow_variants.py | 18 ++++++++++++++++++ InvenTree/part/models.py | 7 +++++++ InvenTree/part/serializers.py | 9 +++++---- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 InvenTree/part/migrations/0066_bomitem_allow_variants.py diff --git a/InvenTree/part/migrations/0066_bomitem_allow_variants.py b/InvenTree/part/migrations/0066_bomitem_allow_variants.py new file mode 100644 index 0000000000..e545c8e3cb --- /dev/null +++ b/InvenTree/part/migrations/0066_bomitem_allow_variants.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2 on 2021-06-01 03:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0065_auto_20210505_2144'), + ] + + operations = [ + migrations.AddField( + model_name='bomitem', + name='allow_variants', + field=models.BooleanField(default=False, help_text='Stock items for variant parts can be used for this BOM item', verbose_name='Allow Variants'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 7db998ab3d..7b9038fecb 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2240,6 +2240,7 @@ class BomItem(models.Model): note: Note field for this BOM item checksum: Validation checksum for the particular BOM line item inherited: This BomItem can be inherited by the BOMs of variant parts + allow_variants: Stock for part variants can be substituted for this BomItem """ def save(self, *args, **kwargs): @@ -2288,6 +2289,12 @@ class BomItem(models.Model): help_text=_('This BOM item is inherited by BOMs for variant parts'), ) + allow_variants = models.BooleanField( + default=False, + verbose_name=_('Allow Variants'), + help_text=_('Stock items for variant parts can be used for this BOM item') + ) + def get_item_hash(self): """ Calculate the checksum hash of this BOM line item: diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 04e0b7a119..d03a37c6dc 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -453,6 +453,7 @@ class BomItemSerializer(InvenTreeModelSerializer): class Meta: model = BomItem fields = [ + 'allow_variants', 'inherited', 'note', 'optional', @@ -460,16 +461,16 @@ class BomItemSerializer(InvenTreeModelSerializer): 'pk', 'part', 'part_detail', + 'purchase_price_avg', + 'purchase_price_max', + 'purchase_price_min', + 'purchase_price_range', 'quantity', 'reference', 'sub_part', 'sub_part_detail', # 'price_range', 'validated', - 'purchase_price_min', - 'purchase_price_max', - 'purchase_price_avg', - 'purchase_price_range', ] From 0bd0e57f160c23dece55edd79eb878bc0295c01e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 14:03:21 +1000 Subject: [PATCH 259/300] BomList can be filtered by "allow_variants" flag --- InvenTree/part/api.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 5bdd572145..b2b70b3030 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -821,6 +821,14 @@ class BomList(generics.ListCreateAPIView): queryset = queryset.filter(inherited=inherited) + # Filter by "allow_variants" + variants = params.get("allow_variants", None) + + if variants is not None: + variants = str2bool(variants) + + queryset = queryset.filter(allow_variants=variants) + # Filter by part? part = params.get('part', None) From 9f407df15a61308a900c4ec218697233eda16d2e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 14:17:31 +1000 Subject: [PATCH 260/300] Update BOM table display --- InvenTree/part/api.py | 2 +- InvenTree/part/forms.py | 1 + InvenTree/templates/js/bom.js | 13 ++++++++++--- InvenTree/templates/js/part.js | 18 ++++++++---------- InvenTree/templates/js/table_filters.js | 4 ++++ 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index b2b70b3030..537b0f9e40 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -827,7 +827,7 @@ class BomList(generics.ListCreateAPIView): if variants is not None: variants = str2bool(variants) - queryset = queryset.filter(allow_variants=variants) + queryset = queryset.filter(allow_variants=variants) # Filter by part? part = params.get('part', None) diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 8f6e3d8898..95de4961f9 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -352,6 +352,7 @@ class EditBomItemForm(HelperForm): 'reference', 'overage', 'note', + 'allow_variants', 'inherited', 'optional', ] diff --git a/InvenTree/templates/js/bom.js b/InvenTree/templates/js/bom.js index e35a51d8bd..7328bcb331 100644 --- a/InvenTree/templates/js/bom.js +++ b/InvenTree/templates/js/bom.js @@ -285,11 +285,18 @@ function loadBomTable(table, options) { title: '{% trans "Optional" %}', searchable: false, formatter: function(value) { - if (value == '1') return '{% trans "true" %}'; - if (value == '0') return '{% trans "false" %}'; + return yesNoLabel(value); } }); + cols.push({ + field: 'allow_variants', + title: '{% trans "Allow Variants" %}', + formatter: function(value) { + return yesNoLabel(value); + } + }) + cols.push({ field: 'inherited', title: '{% trans "Inherited" %}', @@ -297,7 +304,7 @@ function loadBomTable(table, options) { formatter: function(value, row, index, field) { // This BOM item *is* inheritable, but is defined for this BOM if (!row.inherited) { - return "-"; + return yesNoLabel(false); } else if (row.part == options.parent_id) { return '{% trans "Inherited" %}'; } else { diff --git a/InvenTree/templates/js/part.js b/InvenTree/templates/js/part.js index 81cc4e0630..7331ec25e0 100644 --- a/InvenTree/templates/js/part.js +++ b/InvenTree/templates/js/part.js @@ -5,6 +5,14 @@ * Requires api.js to be loaded first */ +function yesNoLabel(value) { + if (value) { + return `{% trans "YES" %}`; + } else { + return `{% trans "NO" %}`; + } +} + function toggleStar(options) { /* Toggle the 'starred' status of a part. * Performs AJAX queries and updates the display on the button. @@ -662,16 +670,6 @@ function loadPartCategoryTable(table, options) { }); } - -function yesNoLabel(value) { - if (value) { - return `{% trans "YES" %}`; - } else { - return `{% trans "NO" %}`; - } -} - - function loadPartTestTemplateTable(table, options) { /* * Load PartTestTemplate table. diff --git a/InvenTree/templates/js/table_filters.js b/InvenTree/templates/js/table_filters.js index 5f516e9419..d02fa50d80 100644 --- a/InvenTree/templates/js/table_filters.js +++ b/InvenTree/templates/js/table_filters.js @@ -49,6 +49,10 @@ function getAvailableTableFilters(tableKey) { inherited: { type: 'bool', title: '{% trans "Inherited" %}', + }, + allow_variants: { + type: 'bool', + title: '{% trans "Allow Variant Stock" %}', } }; } From 7578cab9a8572bcff29b604cbeaa35f9d8e2ac05 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 15:25:39 +1000 Subject: [PATCH 261/300] Add 'bom_item' field to BuildItem model - Required to link the build to the output in case of variant stock --- .../migrations/0028_builditem_bom_item.py | 20 +++++ InvenTree/build/models.py | 82 +++++++++++++++++-- 2 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 InvenTree/build/migrations/0028_builditem_bom_item.py diff --git a/InvenTree/build/migrations/0028_builditem_bom_item.py b/InvenTree/build/migrations/0028_builditem_bom_item.py new file mode 100644 index 0000000000..f93c63dc4c --- /dev/null +++ b/InvenTree/build/migrations/0028_builditem_bom_item.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2 on 2021-06-01 05:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0066_bomitem_allow_variants'), + ('build', '0027_auto_20210404_2016'), + ] + + operations = [ + migrations.AddField( + model_name='builditem', + name='bom_item', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocate_build_items', to='part.bomitem'), + ), + ] diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index c80c0e8523..afe7f335e4 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -1036,7 +1036,19 @@ class Build(MPTTModel): StockModels.StockItem.IN_STOCK_FILTER ) - items = items.filter(part=part) + # Check if variants are allowed for this part + try: + bom_item = PartModels.BomItem.objects.get(part=self.part, sub_part=part) + allow_part_variants = bom_item.allow_variants + except PartModels.BomItem.DoesNotExist: + allow_part_variants = False + + if allow_part_variants: + parts = part.get_descendants(include_self=True) + items = items.filter(part__pk__in=[p.pk for p in parts]) + + else: + items = items.filter(part=part) # Exclude any items which have already been allocated allocated = BuildItem.objects.filter( @@ -1160,10 +1172,6 @@ class BuildItem(models.Model): if self.stock_item.part and self.stock_item.part.trackable and not self.install_into: raise ValidationError(_('Build item must specify a build output, as master part is marked as trackable')) - # Allocated part must be in the BOM for the master part - if self.stock_item.part not in self.build.part.getRequiredParts(recursive=False): - errors['stock_item'] = [_("Selected stock item not found in BOM for part '{p}'").format(p=self.build.part.full_name)] - # Allocated quantity cannot exceed available stock quantity if self.quantity > self.stock_item.quantity: errors['quantity'] = [_("Allocated quantity ({n}) must not exceed available quantity ({q})").format( @@ -1189,6 +1197,61 @@ class BuildItem(models.Model): if len(errors) > 0: raise ValidationError(errors) + """ + Attempt to find the "BomItem" which links this BuildItem to the build. + + - If a BomItem is already set, and it is valid, then we are ok! + """ + + bom_item_valid = False + + if self.bom_item: + """ + A BomItem object has already been assigned. This is valid if: + + a) It points to the same "part" as the referened build + b) Either: + i) The sub_part points to the same part as the referenced StockItem + ii) The BomItem allows variants and the part referenced by the StockItem + is a variant of the sub_part referenced by the BomItem + """ + + if self.build and self.build.part == self.bom_item.part: + + # Check that the sub_part points to the stock_item (either directly or via a variant) + if self.bom_item.sub_part == self.stock_item.part: + bom_item_valid = True + + elif self.bom_item.allow_variants and self.stock_item.part in self.bom_item.sub_part.get_descendants(include_self=False): + bom_item_valid = True + + # If the existing BomItem is *not* valid, try to find a match + if not bom_item_valid: + + if self.build and self.stock_item: + ancestors = self.stock_item.part.get_ancestors(include_self=True, ascending=True) + + for idx, ancestor in enumerate(ancestors): + + try: + bom_item = PartModels.BomItem.objects.get(part=self.build.part, sub_part=ancestor) + except PartModels.BomItem.DoesNotExist: + continue + + # A matching BOM item has been found! + if idx == 0 or bom_item.allow_variants: + bom_item_valid = True + self.bom_item = bom_item + break + + # BomItem did not exist or could not be validated. + # Search for a new one + if not bom_item_valid: + + raise ValidationError({ + 'stock_item': _("Selected stock item not found in BOM for part '{p}'").format(p=self.build.part.full_name) + }) + @transaction.atomic def complete_allocation(self, user): """ @@ -1225,6 +1288,15 @@ class BuildItem(models.Model): help_text=_('Build to allocate parts') ) + # Internal model which links part <-> sub_part + # We need to track this separately, to allow for "variant' stock + bom_item = models.ForeignKey( + PartModels.BomItem, + on_delete=models.CASCADE, + related_name='allocate_build_items', + blank=True, null=True, + ) + stock_item = models.ForeignKey( 'stock.StockItem', on_delete=models.CASCADE, From ab16e1efc3b44d3ba0966a4c996aab1a6294f157 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 15:39:21 +1000 Subject: [PATCH 262/300] Custom migration to find BomItem / BuildItem links where they exist --- .../migrations/0029_auto_20210601_1525.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 InvenTree/build/migrations/0029_auto_20210601_1525.py diff --git a/InvenTree/build/migrations/0029_auto_20210601_1525.py b/InvenTree/build/migrations/0029_auto_20210601_1525.py new file mode 100644 index 0000000000..c5ea04b5c9 --- /dev/null +++ b/InvenTree/build/migrations/0029_auto_20210601_1525.py @@ -0,0 +1,62 @@ +# Generated by Django 3.2 on 2021-06-01 05:25 + +from django.db import migrations + + +def assign_bom_items(apps, schema_editor): + """ + Run through existing BuildItem objects, + and assign a matching BomItem + """ + + BuildItem = apps.get_model('build', 'builditem') + BomItem = apps.get_model('part', 'bomitem') + Part = apps.get_model('part', 'part') + + print("Assigning BomItems to existing BuildItem objects") + + count_valid = 0 + count_total = 0 + + for build_item in BuildItem.objects.all(): + + # Try to find a BomItem which matches the BuildItem + # Note: Before this migration, variant stock assignment was not allowed, + # so BomItem lookup should be pretty easy + + count_total += 1 + + try: + bom_item = BomItem.objects.get( + part__id=build_item.build.part.pk, + sub_part__id=build_item.stock_item.part.pk, + ) + + build_item.bom_item = bom_item + build_item.save() + + count_valid += 1 + + except BomItem.DoesNotExist: + pass + + print(f"Assigned BomItem for {count_valid}/{count_total} entries") + + +def unassign_bom_items(apps, schema_editor): + """ + Reverse migration does not do anything. + Function here to preserve ability to reverse migration + """ + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('build', '0028_builditem_bom_item'), + ] + + operations = [ + migrations.RunPython(assign_bom_items, reverse_code=unassign_bom_items), + ] From 9baf856d755314858db8556721c3679f6e673da6 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 16:14:26 +1000 Subject: [PATCH 263/300] Fixes for build item allocation rendering --- InvenTree/InvenTree/version.py | 6 +++++- InvenTree/build/models.py | 13 +++++++++++++ InvenTree/build/serializers.py | 6 ++++-- InvenTree/templates/js/build.js | 12 +++++++++++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index a736bfe6a1..7b8546b1c2 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -16,9 +16,13 @@ Increment thi API version number whenever there is a significant change to the A v3 -> 2021-05-22: - The updated StockItem "history tracking" now uses a different interface +v4 -> 2021-06-01 + - BOM items can now accept "variant stock" to be assigned against them + - Many slight API tweaks were needed to get this to work properly! + """ -INVENTREE_API_VERSION = 3 +INVENTREE_API_VERSION = 4 def inventreeInstanceName(): diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index afe7f335e4..031eb09303 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -30,6 +30,7 @@ from InvenTree.models import InvenTreeAttachment import common.models import InvenTree.fields +import InvenTree.helpers from stock import models as StockModels from part import models as PartModels @@ -1280,6 +1281,18 @@ class BuildItem(models.Model): # Simply remove the items from stock item.take_stock(self.quantity, user) + def getStockItemThumbnail(self): + """ + Return qualified URL for part thumbnail image + """ + + if self.stock_item and self.stock_item.part: + return InvenTree.helpers.getMediaUrl(self.stock_item.part.image.thumbnail.url) + elif self.bom_item and self.stock_item.sub_part: + return InvenTree.helpers.getMediaUrl(self.bom_item.sub_part.image.thumbnail.url) + else: + return InvenTree.helpers.getBlankThumbnail() + build = models.ForeignKey( Build, on_delete=models.CASCADE, diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py index 550a3c3a85..629422f6e5 100644 --- a/InvenTree/build/serializers.py +++ b/InvenTree/build/serializers.py @@ -97,9 +97,10 @@ class BuildSerializer(InvenTreeModelSerializer): class BuildItemSerializer(InvenTreeModelSerializer): """ Serializes a BuildItem object """ + bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True) part = serializers.IntegerField(source='stock_item.part.pk', read_only=True) part_name = serializers.CharField(source='stock_item.part.full_name', read_only=True) - part_image = serializers.CharField(source='stock_item.part.image', read_only=True) + part_thumb = serializers.CharField(source='getStockItemThumbnail', read_only=True) stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True) quantity = serializers.FloatField() @@ -108,11 +109,12 @@ class BuildItemSerializer(InvenTreeModelSerializer): model = BuildItem fields = [ 'pk', + 'bom_part', 'build', 'install_into', 'part', 'part_name', - 'part_image', + 'part_thumb', 'stock_item', 'stock_item_detail', 'quantity' diff --git a/InvenTree/templates/js/build.js b/InvenTree/templates/js/build.js index 0233974741..9523d24d39 100644 --- a/InvenTree/templates/js/build.js +++ b/InvenTree/templates/js/build.js @@ -372,7 +372,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { data.forEach(function(item) { // Group BuildItem objects by part - var part = item.part; + var part = item.bom_part || item.part; var key = parseInt(part); if (!(key in allocations)) { @@ -461,6 +461,16 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { data: row.allocations, showHeader: true, columns: [ + { + field: 'part', + title: '{% trans "Part" %}', + formatter: function(value, row) { + + var html = imageHoverIcon(row.part_thumb); + html += renderLink(row.part_name, `/part/${value}/`); + return html; + } + }, { width: '50%', field: 'quantity', From ee9df039cbba39864de34d7a425f22bfed66c532 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 16:19:24 +1000 Subject: [PATCH 264/300] allocatedItems function now takes variants into account --- InvenTree/build/models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 031eb09303..03a49b627f 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -881,9 +881,12 @@ class Build(MPTTModel): output - Build output (StockItem). """ + # Remember, if 'variant' stock is allowed to be allocated, it becomes more complicated! + variants = part.get_descendants(include_self=True) + allocations = BuildItem.objects.filter( build=self, - stock_item__part=part, + stock_item__part__pk__in=[p.pk for p in variants], install_into=output, ) From b31796cbebc18f83517b7d03da90a717d5d1cb23 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 1 Jun 2021 16:40:02 +1000 Subject: [PATCH 265/300] Simplified "installed_in" table --- InvenTree/templates/js/stock.js | 337 +++++++------------------------- 1 file changed, 76 insertions(+), 261 deletions(-) diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 1a052b5fa1..151265a3ae 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -1304,33 +1304,6 @@ function createNewStockItem(options) { function loadInstalledInTable(table, options) { /* * Display a table showing the stock items which are installed in this stock item. - * This is a multi-level tree table, where the "top level" items are Part objects, - * and the children of each top-level item are the associated installed stock items. - * - * The process for retrieving data and displaying the table is as follows: - * - * A) Get BOM data for the stock item - * - It is assumed that the stock item will be for an assembly - * (otherwise why are we installing stuff anyway?) - * - Request BOM items for stock_item.part (and only for trackable sub items) - * - * B) Add parts to table - * - Create rows for each trackable sub-part in the table - * - * C) Gather installed stock item data - * - Get the list of installed stock items via the API - * - If the Part reference is already in the table, add the sub-item as a child - * - If this is a stock item for a *new* part, request that part from the API, - * and add that part as a new row, then add the stock item as a child of that part - * - * D) Enjoy! - * - * - * And the options object contains the following things: - * - * - stock_item: The PK of the master stock_item object - * - part: The PK of the Part reference of the stock_item object - * - quantity: The quantity of the stock item */ function updateCallbacks() { @@ -1353,246 +1326,88 @@ function loadInstalledInTable(table, options) { }); } - table.inventreeTable( - { - url: "{% url 'api-bom-list' %}", - queryParams: { - part: options.part, - sub_part_trackable: true, - sub_part_detail: true, - }, - showColumns: false, - name: 'installed-in', - detailView: true, - detailViewByClick: true, - detailFilter: function(index, row) { - return row.installed_count && row.installed_count > 0; - }, - detailFormatter: function(index, row, element) { - var subTableId = `installed-table-${row.sub_part}`; + table.inventreeTable({ + url: "{% url 'api-stock-list' %}", + queryParams: { + installed_in: options.stock_item, + part_detail: true, + }, + formatNoMatches: function() { + return '{% trans "No installed items" %}'; + }, + columns: [ + { + field: 'part', + title: '{% trans "Part" %}', + formatter: function(value, row) { + var html = ''; - var html = `
    `; + html += imageHoverIcon(row.part_detail.thumbnail); + html += renderLink(row.part_detail.full_name, `/stock/item/${row.pk}/`); - element.html(html); - - var subTable = $(`#${subTableId}`); - - // Display a "sub table" showing all the linked stock items - subTable.bootstrapTable({ - data: row.installed_items, - showHeader: true, - columns: [ - { - field: 'item', - title: '{% trans "Stock Item" %}', - formatter: function(value, subrow, index, field) { - - var pk = subrow.pk; - var html = ''; - - if (subrow.serial && subrow.quantity == 1) { - html += `{% trans "Serial" %}: ${subrow.serial}`; - } else { - html += `{% trans "Quantity" %}: ${subrow.quantity}`; - } - - return renderLink(html, `/stock/item/${subrow.pk}/`); - }, - }, - { - field: 'status', - title: '{% trans "Status" %}', - formatter: function(value, subrow, index, field) { - return stockStatusDisplay(value); - } - }, - { - field: 'batch', - title: '{% trans "Batch" %}', - }, - { - field: 'actions', - title: '', - formatter: function(value, subrow, index) { - - var pk = subrow.pk; - var html = ''; - - // Add some buttons yo! - html += `
    `; - - html += makeIconButton('fa-unlink', 'button-uninstall', pk, "{% trans 'Uninstall stock item' %}"); - - html += `
    `; - - return html; - } - } - ], - onPostBody: function() { - // Setup button callbacks - subTable.find('.button-uninstall').click(function() { - var pk = $(this).attr('pk'); - - launchModalForm( - "{% url 'stock-item-uninstall' %}", - { - data: { - 'items[]': [pk], - }, - success: function() { - // Refresh entire table! - table.bootstrapTable('refresh'); - } - } - ); - }); - } - }); - }, - columns: [ - { - checkbox: true, - title: '{% trans "Select" %}', - searchable: false, - switchable: false, - }, - { - field: 'pk', - title: 'ID', - visible: false, - switchable: false, - }, - { - field: 'part', - title: '{% trans "Part" %}', - sortable: true, - formatter: function(value, row, index, field) { - - var url = `/part/${row.sub_part}/`; - var thumb = row.sub_part_detail.thumbnail; - var name = row.sub_part_detail.full_name; - - html = imageHoverIcon(thumb) + renderLink(name, url); - - if (row.not_in_bom) { - html = `${html}` - } - - return html; - } - }, - { - field: 'installed', - title: '{% trans "Installed" %}', - sortable: false, - formatter: function(value, row, index, field) { - // Construct a progress showing how many items have been installed - - var installed = row.installed_count || 0; - var required = row.quantity || 0; - - required *= options.quantity; - - var progress = makeProgressBar(installed, required, { - id: row.sub_part.pk, - }); - - return progress; - } - }, - { - field: 'actions', - switchable: false, - formatter: function(value, row) { - var pk = row.sub_part; - - var html = `
    `; - - html += makeIconButton('fa-link', 'button-install', pk, '{% trans "Install item" %}'); - - html += `
    `; - - return html; - } + return html; } - ], - onLoadSuccess: function() { - // Grab a list of parts which are actually installed in this stock item + }, + { + field: 'quantity', + title: '{% trans "Quantity" %}', + formatter: function(value, row) { - inventreeGet( - "{% url 'api-stock-list' %}", + var html = ''; + + if (row.serial && row.quantity == 1) { + html += `{% trans "Serial" %}: ${row.serial}`; + } else { + html += `${row.quantity}`; + } + + return renderLink(html, `/stock/item/${row.pk}/`); + } + }, + { + field: 'status', + title: '{% trans "Status" %}', + formatter: function(value, row) { + return stockStatusDisplay(value); + } + }, + { + field: 'batch', + title: '{% trans "Batch" %}', + }, + { + field: 'buttons', + title: '', + switchable: false, + formatter: function(value, row) { + var pk = row.pk; + var html = ''; + + html += `
    `; + html += makeIconButton('fa-unlink', 'button-uninstall', pk, '{% trans "Uninstall Stock Item" %}'); + html += `
    `; + + return html; + } + } + ], + onPostBody: function() { + // Assign callbacks to the buttons + table.find('.button-uninstall').click(function() { + var pk = $(this).attr('pk'); + + launchModalForm( + '{% url "stock-item-uninstall" %}', { - installed_in: options.stock_item, - part_detail: true, - }, - { - success: function(stock_items) { - - var table_data = table.bootstrapTable('getData'); - - stock_items.forEach(function(item) { - - var match = false; - - for (var idx = 0; idx < table_data.length; idx++) { - - var row = table_data[idx]; - - // Check each row in the table to see if this stock item matches - table_data.forEach(function(row) { - - // Match on "sub_part" - if (row.sub_part == item.part) { - - // First time? - if (row.installed_count == null) { - row.installed_count = 0; - row.installed_items = []; - } - - row.installed_count += item.quantity; - row.installed_items.push(item); - - // Push the row back into the table - table.bootstrapTable('updateRow', idx, row, true); - - match = true; - } - - }); - - if (match) { - break; - } - } - - if (!match) { - // The stock item did *not* match any items in the BOM! - // Add a new row to the table... - - // Contruct a new "row" to add to the table - var new_row = { - sub_part: item.part, - sub_part_detail: item.part_detail, - not_in_bom: true, - installed_count: item.quantity, - installed_items: [item], - }; - - table.bootstrapTable('append', [new_row]); - - } - }); - - // Update button callback links - updateCallbacks(); + data: { + 'items[]': pk, + }, + success: function() { + table.bootstrapTable('refresh'); } } - ); - - updateCallbacks(); - }, + ) + }); } - ); + }); } \ No newline at end of file From ffaa6ee3a92ac7b1d56d1b1fdbd647008d3c39b7 Mon Sep 17 00:00:00 2001 From: eeintech Date: Tue, 1 Jun 2021 14:22:00 -0400 Subject: [PATCH 266/300] Fixed price break row actions after sorting --- InvenTree/company/templates/company/supplier_part_pricing.html | 2 +- InvenTree/part/templates/part/sale_prices.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/company/templates/company/supplier_part_pricing.html b/InvenTree/company/templates/company/supplier_part_pricing.html index febae74f47..9da3f3df7e 100644 --- a/InvenTree/company/templates/company/supplier_part_pricing.html +++ b/InvenTree/company/templates/company/supplier_part_pricing.html @@ -40,7 +40,7 @@ $('#price-break-table').inventreeTable({ part: {{ part.id }}, }, url: "{% url 'api-part-supplier-price' %}", - onLoadSuccess: function() { + onPostBody: function() { var table = $('#price-break-table'); table.find('.button-price-break-delete').click(function() { diff --git a/InvenTree/part/templates/part/sale_prices.html b/InvenTree/part/templates/part/sale_prices.html index f19d65a59a..4ec826e2a6 100644 --- a/InvenTree/part/templates/part/sale_prices.html +++ b/InvenTree/part/templates/part/sale_prices.html @@ -48,7 +48,7 @@ $('#price-break-table').inventreeTable({ part: {{ part.id }}, }, url: "{% url 'api-part-sale-price-list' %}", - onLoadSuccess: function() { + onPostBody: function() { var table = $('#price-break-table'); table.find('.button-price-break-delete').click(function() { From 7d7e518c1bc5e4f0a97fe9624a453cde02ff6e3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 21:37:26 +0000 Subject: [PATCH 267/300] Bump django from 3.2 to 3.2.1 Bumps [django](https://github.com/django/django) from 3.2 to 3.2.1. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2...3.2.1) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4f592bf9ab..66dabae630 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ invoke>=1.4.0 # Invoke build tool wheel>=0.34.2 # Wheel -Django==3.2 # Django package +Django==3.2.1 # Django package pillow==8.1.1 # Image manipulation djangorestframework==3.12.4 # DRF framework django-cors-headers==3.2.0 # CORS headers extension for DRF From d87592aedb209e34562c6a443221ddec66673cb2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 13:22:11 +0200 Subject: [PATCH 268/300] use the default currency in forms --- InvenTree/common/models.py | 2 +- InvenTree/company/forms.py | 5 +++-- InvenTree/order/models.py | 6 ++++-- InvenTree/stock/models.py | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 236e48770f..ec76475901 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -703,7 +703,7 @@ class PriceBreak(models.Model): price = MoneyField( max_digits=19, decimal_places=4, - default_currency='USD', + default_currency=currency_code_default(), null=True, verbose_name=_('Price'), help_text=_('Unit price at specified quantity'), diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index 62a46fcd6f..fc409b9a77 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -15,6 +15,7 @@ import djmoney.settings from djmoney.forms.fields import MoneyField import common.settings +from common.settings import currency_code_default from .models import Company from .models import ManufacturerPart @@ -38,7 +39,7 @@ class EditCompanyForm(HelperForm): label=_('Currency'), help_text=_('Default currency used for this company'), choices=[('', '----------')] + djmoney.settings.CURRENCY_CHOICES, - initial=common.settings.currency_code_default, + initial=currency_code_default, ) class Meta: @@ -116,7 +117,7 @@ class EditSupplierPartForm(HelperForm): single_pricing = MoneyField( label=_('Single Price'), - default_currency='USD', + default_currency=currency_code_default(), help_text=_('Single quantity price'), decimal_places=4, max_digits=19, diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index fb169e0536..49504b6d89 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -17,6 +17,8 @@ from django.contrib.auth.models import User from django.urls import reverse from django.utils.translation import ugettext_lazy as _ +from common.settings import currency_code_default + from markdownx.models import MarkdownxField from djmoney.models.fields import MoneyField @@ -664,7 +666,7 @@ class PurchaseOrderLineItem(OrderLineItem): purchase_price = MoneyField( max_digits=19, decimal_places=4, - default_currency='USD', + default_currency=currency_code_default(), null=True, blank=True, verbose_name=_('Purchase Price'), help_text=_('Unit purchase price'), @@ -693,7 +695,7 @@ class SalesOrderLineItem(OrderLineItem): sale_price = MoneyField( max_digits=19, decimal_places=4, - default_currency='USD', + default_currency=currency_code_default(), null=True, blank=True, verbose_name=_('Sale Price'), help_text=_('Unit sale price'), diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 88f8dd081c..9786b360d9 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -20,6 +20,8 @@ from django.contrib.auth.models import User from django.db.models.signals import pre_delete from django.dispatch import receiver +from common.settings import currency_code_default + from markdownx.models import MarkdownxField from mptt.models import MPTTModel, TreeForeignKey @@ -534,7 +536,7 @@ class StockItem(MPTTModel): purchase_price = MoneyField( max_digits=19, decimal_places=4, - default_currency='USD', + default_currency=currency_code_default(), blank=True, null=True, verbose_name=_('Purchase Price'), From 691142ea4c539a252bcc468a5cfd704e27ca7687 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 13:27:39 +0200 Subject: [PATCH 269/300] fixing currency display --- InvenTree/part/templates/part/part_pricing.html | 3 ++- InvenTree/templates/price.html | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/templates/part/part_pricing.html b/InvenTree/part/templates/part/part_pricing.html index 49e37fe0ad..cc036a5884 100644 --- a/InvenTree/part/templates/part/part_pricing.html +++ b/InvenTree/part/templates/part/part_pricing.html @@ -1,8 +1,9 @@ {% extends "modal_form.html" %} -{% load i18n %} +{% load i18n inventree_extras %} {% block pre_form_content %} +{% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} diff --git a/InvenTree/templates/price.html b/InvenTree/templates/price.html index ef47d5edf2..285f785178 100644 --- a/InvenTree/templates/price.html +++ b/InvenTree/templates/price.html @@ -1 +1,2 @@ -{% if currency %}{{ currency.symbol }}{% endif %}{{ price }}{% if currency %} {{ currency.suffix }}{% endif %} \ No newline at end of file +{% load djmoney %} +{% money_localize price currency %} \ No newline at end of file From 0eff7d000af96d779f88e5e24ec6738b989d4767 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 15:05:05 +0200 Subject: [PATCH 270/300] added tag to replace dynamic setting --- InvenTree/part/templatetags/inventree_extras.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index ceb2d11e31..1c40dae30e 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -18,6 +18,7 @@ from InvenTree import version, settings import InvenTree.helpers from common.models import InvenTreeSetting, ColorTheme +from common.settings import currency_code_default register = template.Library() @@ -161,6 +162,12 @@ def inventree_credits_url(*args, **kwargs): return "https://inventree.readthedocs.io/en/latest/credits/" +@register.simple_tag() +def default_currency(*args, **kwargs): + """ Returns the default currency code """ + return currency_code_default() + + @register.simple_tag() def setting_object(key, *args, **kwargs): """ From 44717b646f48fb60c3f4dd526cfb289e8b883893 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 15:07:42 +0200 Subject: [PATCH 271/300] using new tag for currency --- InvenTree/part/templates/part/order_prices.html | 4 ++-- InvenTree/part/templates/part/part_pricing.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/templates/part/order_prices.html b/InvenTree/part/templates/part/order_prices.html index 6c5b2173bf..e165ee9c74 100644 --- a/InvenTree/part/templates/part/order_prices.html +++ b/InvenTree/part/templates/part/order_prices.html @@ -13,7 +13,7 @@ {% endblock %} {% block details %} -{% settings_value "INVENTREE_DEFAULT_CURRENCY" as currency %} +{% default_currency as currency %} {% crispy form %} @@ -130,7 +130,7 @@ the part single price shown is the current price for that supplier part"> From 05d79a4c1949972d822b8a2b51aeda9c788451db Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 15:18:08 +0200 Subject: [PATCH 272/300] same nav sidebar distance for everything --- InvenTree/InvenTree/static/css/inventree.css | 4 +++ InvenTree/build/templates/build/navbar.html | 12 +++---- .../company/manufacturer_part_navbar.html | 6 ++-- .../company/templates/company/navbar.html | 16 ++++----- .../company/supplier_part_navbar.html | 6 ++-- .../order/templates/order/po_navbar.html | 10 +++--- .../order/templates/order/so_navbar.html | 8 ++--- .../part/templates/part/category_navbar.html | 6 ++-- InvenTree/part/templates/part/navbar.html | 36 +++++++++---------- .../templates/stock/location_navbar.html | 4 +-- InvenTree/stock/templates/stock/navbar.html | 12 +++---- 11 files changed, 62 insertions(+), 58 deletions(-) diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css index 0aab04f941..eed6c6ad21 100644 --- a/InvenTree/InvenTree/static/css/inventree.css +++ b/InvenTree/InvenTree/static/css/inventree.css @@ -957,3 +957,7 @@ input[type="date"].form-control, input[type="time"].form-control, input[type="da .clip-btn:hover { background: var(--label-grey); } + +.sidebar-icon { + min-width: 19px; +} \ No newline at end of file diff --git a/InvenTree/build/templates/build/navbar.html b/InvenTree/build/templates/build/navbar.html index 34d3b9e9e4..e6d2e644ce 100644 --- a/InvenTree/build/templates/build/navbar.html +++ b/InvenTree/build/templates/build/navbar.html @@ -11,7 +11,7 @@
  • - + {% trans "Details" %}
  • @@ -20,7 +20,7 @@
  • - + {% trans "Allocate Stock" %}
  • @@ -28,28 +28,28 @@
  • - + {% trans "Build Outputs" %}
  • - + {% trans "Child Builds" %}
  • - + {% trans "Attachments" %}
  • - + {% trans "Notes" %}
  • diff --git a/InvenTree/company/templates/company/manufacturer_part_navbar.html b/InvenTree/company/templates/company/manufacturer_part_navbar.html index 96b6bec699..3eae30afaf 100644 --- a/InvenTree/company/templates/company/manufacturer_part_navbar.html +++ b/InvenTree/company/templates/company/manufacturer_part_navbar.html @@ -10,7 +10,7 @@
  • - + {% trans "Suppliers" %}
  • @@ -18,14 +18,14 @@ {% comment "for later" %}
  • - + {% trans "Stock" %}
  • - + {% trans "Orders" %}
  • diff --git a/InvenTree/company/templates/company/navbar.html b/InvenTree/company/templates/company/navbar.html index 8804dc2635..715d448b0f 100644 --- a/InvenTree/company/templates/company/navbar.html +++ b/InvenTree/company/templates/company/navbar.html @@ -11,7 +11,7 @@
  • - + {% trans "Details" %}
  • @@ -19,7 +19,7 @@ {% if company.is_manufacturer %}
  • - + {% trans "Manufactured Parts" %}
  • @@ -28,7 +28,7 @@ {% if company.is_supplier or company.is_manufacturer %}
  • - + {% trans "Supplied Parts" %}
  • @@ -37,7 +37,7 @@ {% if company.is_manufacturer or company.is_supplier %}
  • - + {% trans "Stock" %}
  • @@ -46,7 +46,7 @@ {% if company.is_supplier %}
  • - + {% trans "Purchase Orders" %}
  • @@ -55,13 +55,13 @@ {% if company.is_customer %}
  • - + {% trans "Sales Orders" %}
  • - + {% trans "Assigned Stock" %}
  • @@ -69,7 +69,7 @@
  • - + {% trans "Notes" %}
  • diff --git a/InvenTree/company/templates/company/supplier_part_navbar.html b/InvenTree/company/templates/company/supplier_part_navbar.html index 09c3bc0443..e52c1798ba 100644 --- a/InvenTree/company/templates/company/supplier_part_navbar.html +++ b/InvenTree/company/templates/company/supplier_part_navbar.html @@ -11,21 +11,21 @@
  • - + {% trans "Stock" %}
  • - + {% trans "Orders" %}
  • - + {% trans "Pricing" %}
  • diff --git a/InvenTree/order/templates/order/po_navbar.html b/InvenTree/order/templates/order/po_navbar.html index f8e818c2e3..4dc501a8d6 100644 --- a/InvenTree/order/templates/order/po_navbar.html +++ b/InvenTree/order/templates/order/po_navbar.html @@ -11,33 +11,33 @@
  • - + {% trans "Details" %}
  • {% if order.status == PurchaseOrderStatus.PENDING and roles.purchase_order.change %}
  • - + {% trans "Upload File" %}
  • {% endif %}
  • - + {% trans "Received Items" %}
  • - + {% trans "Attachments" %}
  • - + {% trans "Notes" %}
  • diff --git a/InvenTree/order/templates/order/so_navbar.html b/InvenTree/order/templates/order/so_navbar.html index 847e0a22f6..4623febd02 100644 --- a/InvenTree/order/templates/order/so_navbar.html +++ b/InvenTree/order/templates/order/so_navbar.html @@ -11,28 +11,28 @@
  • - + {% trans "Details" %}
  • - + {% trans "Build Orders" %}
  • - + {% trans "Attachments" %}
  • - + {% trans "Notes" %}
  • diff --git a/InvenTree/part/templates/part/category_navbar.html b/InvenTree/part/templates/part/category_navbar.html index e723db358d..d84b49a311 100644 --- a/InvenTree/part/templates/part/category_navbar.html +++ b/InvenTree/part/templates/part/category_navbar.html @@ -14,7 +14,7 @@ {% else %} {% endif %} - + {% trans "Subcategories" %} @@ -25,7 +25,7 @@ {% else %} {% endif %} - + {% trans "Parts" %} @@ -33,7 +33,7 @@ {% if category %}
  • - + {% trans "Parameters" %}
  • diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html index a2c8104486..d1ed7e3d21 100644 --- a/InvenTree/part/templates/part/navbar.html +++ b/InvenTree/part/templates/part/navbar.html @@ -10,7 +10,7 @@
  • - + {% trans "Details" %} @@ -18,28 +18,28 @@
  • - + {% trans "Parameters" %}
  • {% if part.is_template %}
  • - + {% trans "Variants" %}
  • {% endif %}
  • - + {% trans "Stock" %}
  • {% if part.component or part.salable %}
  • - + {% trans "Allocations" %}
  • @@ -47,14 +47,14 @@ {% if part.assembly %}
  • - + {% trans "Bill of Materials" %}
  • {% if roles.build.view %}
  • - + {% trans "Build Orders" %}
  • @@ -63,7 +63,7 @@ {% if part.component %}
  • - + {% trans "Used In" %}
  • @@ -71,25 +71,25 @@ {% if part.purchaseable and roles.purchase_order.view %}
  • - + {% trans "Order Price" %}
  • - + {% trans "Manufacturers" %}
  • - + {% trans "Suppliers" %}
  • - + {% trans "Purchase Orders" %}
  • @@ -97,13 +97,13 @@ {% if part.salable and roles.sales_order.view %}
  • - + {% trans "Sale Price" %}
  • - + {% trans "Sales Orders" %}
  • @@ -111,26 +111,26 @@ {% if part.trackable %}
  • - + {% trans "Tests" %}
  • {% endif %}
  • - + {% trans "Related Parts" %}
  • - + {% trans "Attachments" %}
  • - + {% trans "Notes" %}
  • diff --git a/InvenTree/stock/templates/stock/location_navbar.html b/InvenTree/stock/templates/stock/location_navbar.html index 0cb0c9d1eb..a4974d0d37 100644 --- a/InvenTree/stock/templates/stock/location_navbar.html +++ b/InvenTree/stock/templates/stock/location_navbar.html @@ -14,7 +14,7 @@ {% else %} {% endif %} - + {% trans "Sublocations" %} @@ -25,7 +25,7 @@ {% else %} {% endif %} - + {% trans "Stock Items" %} diff --git a/InvenTree/stock/templates/stock/navbar.html b/InvenTree/stock/templates/stock/navbar.html index 28a0bb2a5d..7c7d197a1a 100644 --- a/InvenTree/stock/templates/stock/navbar.html +++ b/InvenTree/stock/templates/stock/navbar.html @@ -10,7 +10,7 @@
  • - + {% trans "History" %}
  • @@ -18,7 +18,7 @@ {% if item.part.trackable %}
  • - + {% trans "Test Data" %}
  • @@ -26,7 +26,7 @@ {% if item.part.assembly %}
  • - + {% trans "Installed Items" %}
  • @@ -37,7 +37,7 @@ {% if item.child_count > 0 %}
  • - + {% trans "Children" %}
  • @@ -46,14 +46,14 @@
  • - + {% trans "Attachments" %}
  • - + {% trans "Notes" %}
  • From 0bac7ebf3e1b0eee48f6fa36005de61238b7b520 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 5 Jun 2021 17:18:46 +0200 Subject: [PATCH 273/300] styling --- InvenTree/company/forms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py index fc409b9a77..6ffa94b746 100644 --- a/InvenTree/company/forms.py +++ b/InvenTree/company/forms.py @@ -14,7 +14,6 @@ import django.forms import djmoney.settings from djmoney.forms.fields import MoneyField -import common.settings from common.settings import currency_code_default from .models import Company From 172700da105f73f192b9bbe7f372350878011d4b Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 7 Jun 2021 00:12:52 +1000 Subject: [PATCH 274/300] Update django-import-export to 2.5.0 - Fixes an export error introduced after updating to latest django --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 66dabae630..5600221c94 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,9 +11,8 @@ django-markdownx==3.0.1 # Markdown form fields django-markdownify==0.8.0 # Markdown rendering coreapi==2.3.0 # API documentation pygments==2.7.4 # Syntax highlighting -# tablib==0.13.0 # Import / export data files (installed as dependency of django-import-export package) django-crispy-forms==1.11.2 # Form helpers -django-import-export==2.0.0 # Data import / export for admin interface +django-import-export==2.5.0 # Data import / export for admin interface tablib[xls,xlsx,yaml] # Support for XLS and XLSX formats django-cleanup==5.1.0 # Manage deletion of old / unused uploaded files flake8==3.8.3 # PEP checking From 3aadf94a9cecce0b86653e9dda0a08c4e906ece9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 8 Jun 2021 16:15:40 +1000 Subject: [PATCH 275/300] Stock Test: Fix display of stock test table - Incorrect parent node was set --- InvenTree/templates/js/stock.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 151265a3ae..0ce10b28a7 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -159,7 +159,7 @@ function loadStockTestResultsTable(table, options) { // Set "parent" for each existing row tableData.forEach(function(item, idx) { - tableData[idx].parent = options.stock_item; + tableData[idx].parent = parent_node; }); // Once the test template data are loaded, query for test results From 2a059f345e9b109e4dd082912926ecfef1052c6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Jun 2021 19:49:34 +0000 Subject: [PATCH 276/300] Build(deps): Bump pillow from 8.1.1 to 8.2.0 Bumps [pillow](https://github.com/python-pillow/Pillow) from 8.1.1 to 8.2.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/8.1.1...8.2.0) --- updated-dependencies: - dependency-name: pillow dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5600221c94..43456990ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ invoke>=1.4.0 # Invoke build tool wheel>=0.34.2 # Wheel Django==3.2.1 # Django package -pillow==8.1.1 # Image manipulation +pillow==8.2.0 # Image manipulation djangorestframework==3.12.4 # DRF framework django-cors-headers==3.2.0 # CORS headers extension for DRF django-filter==2.4.0 # Extended filtering options From 9fd212d1b21216e790744d4e1b0c44b6e665c8cb Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 9 Jun 2021 09:41:27 +1000 Subject: [PATCH 277/300] BuildItemSerializer: Handle errors when thumbnail is not found --- InvenTree/build/models.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 03a49b627f..f34d3c1d43 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -1289,10 +1289,23 @@ class BuildItem(models.Model): Return qualified URL for part thumbnail image """ + thumb_url = None + if self.stock_item and self.stock_item.part: - return InvenTree.helpers.getMediaUrl(self.stock_item.part.image.thumbnail.url) - elif self.bom_item and self.stock_item.sub_part: - return InvenTree.helpers.getMediaUrl(self.bom_item.sub_part.image.thumbnail.url) + try: + # Try to extract the thumbnail + thumb_url = self.stock_item.part.image.thumbnail.url + except: + pass + + if thumb_url is None and self.bom_item and self.stock_item.sub_part: + try: + thumb_url = self.bom_item.sub_part.image.thumbnail.url + except: + pass + + if thumb_url is not None: + return InvenTree.helpers.getMediaUrl(thumb_url) else: return InvenTree.helpers.getBlankThumbnail() From 0c14457598753eed4e1d85fad3ebf217bbc13d0d Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 9 Jun 2021 11:16:37 +1000 Subject: [PATCH 278/300] Fix typo in getStockItemThumbnail --- InvenTree/build/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index f34d3c1d43..fad5a2934d 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -1298,7 +1298,7 @@ class BuildItem(models.Model): except: pass - if thumb_url is None and self.bom_item and self.stock_item.sub_part: + if thumb_url is None and self.bom_item and self.bom_item.sub_part: try: thumb_url = self.bom_item.sub_part.image.thumbnail.url except: From 6e2abc4cde021fcf548fed1323951aab83491365 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jun 2021 17:26:23 +0000 Subject: [PATCH 279/300] Build(deps): Bump django from 3.2.1 to 3.2.2 Bumps [django](https://github.com/django/django) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.1...3.2.2) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 43456990ea..3eb31a900b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ invoke>=1.4.0 # Invoke build tool wheel>=0.34.2 # Wheel -Django==3.2.1 # Django package +Django==3.2.2 # Django package pillow==8.2.0 # Image manipulation djangorestframework==3.12.4 # DRF framework django-cors-headers==3.2.0 # CORS headers extension for DRF From 0bc190bca5143aff588020ff41a8e7edb3ddadd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:36:17 +0000 Subject: [PATCH 280/300] Build(deps): Bump django from 3.2.2 to 3.2.4 Bumps [django](https://github.com/django/django) from 3.2.2 to 3.2.4. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/3.2.2...3.2.4) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3eb31a900b..abcf2cb098 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ invoke>=1.4.0 # Invoke build tool wheel>=0.34.2 # Wheel -Django==3.2.2 # Django package +Django==3.2.4 # Django package pillow==8.2.0 # Image manipulation djangorestframework==3.12.4 # DRF framework django-cors-headers==3.2.0 # CORS headers extension for DRF From c0e50128dd988c39294c9563faf22ee9ff28eb85 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 11 Jun 2021 23:43:23 +0200 Subject: [PATCH 281/300] display latest serial on all part-views #1648 --- InvenTree/part/templates/part/part_base.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index ec296d4174..2e1cb2e71f 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -181,6 +181,14 @@ {% endif %} {% endif %} {% endif %} + {% if part.trackable and part.getLatestSerialNumber %} +
    + + + + + + {% endif %}
    {% trans 'Part' %}
    {% trans 'Part' %}
    {% trans "Latest Serial Number" %}{{ part.getLatestSerialNumber }}{% include "clip.html"%}
    From ec19d7752365b16e38305e71a632ad3a0d4731c7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 13 Jun 2021 20:08:42 +0200 Subject: [PATCH 282/300] fix whitespaces in paths --- tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks.py b/tasks.py index 88bd5e42e4..5aab30651a 100644 --- a/tasks.py +++ b/tasks.py @@ -282,7 +282,7 @@ def export_records(c, filename='data.json'): tmpfile = f"{filename}.tmp" - cmd = f"dumpdata --indent 2 --output {tmpfile} {content_excludes()}" + cmd = f"dumpdata --indent 2 --output '{tmpfile}' {content_excludes()}" # Dump data to temporary file manage(c, cmd, pty=True) @@ -348,7 +348,7 @@ def import_records(c, filename='data.json'): with open(tmpfile, "w") as f_out: f_out.write(json.dumps(data, indent=2)) - cmd = f"loaddata {tmpfile} -i {content_excludes()}" + cmd = f"loaddata '{tmpfile}' -i {content_excludes()}" manage(c, cmd, pty=True) From 08fbdf660bf4ca92c60229ef5f3d590b1fe925e6 Mon Sep 17 00:00:00 2001 From: eeintech Date: Mon, 14 Jun 2021 14:19:10 -0400 Subject: [PATCH 283/300] Fix for #1661 --- InvenTree/stock/serializers.py | 8 ++++++++ InvenTree/templates/js/stock.js | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 9bcdc5182e..d60689ccef 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -161,6 +161,13 @@ class StockItemSerializer(InvenTreeModelSerializer): required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False) + purchase_price = serializers.SerializerMethodField() + + def get_purchase_price(self, obj): + """ Return purchase_price (Money field) as string (includes currency) """ + + return str(obj.purchase_price) if obj.purchase_price else '-' + def __init__(self, *args, **kwargs): part_detail = kwargs.pop('part_detail', False) @@ -215,6 +222,7 @@ class StockItemSerializer(InvenTreeModelSerializer): 'tracking_items', 'uid', 'updated', + 'purchase_price', ] """ These fields are read-only in this context. diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index 0ce10b28a7..4e992df67f 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -660,6 +660,11 @@ function loadStockTable(table, options) { title: '{% trans "Last Updated" %}', sortable: true, }, + { + field: 'purchase_price', + title: '{% trans "Purchase Price" %}', + sortable: true, + }, { field: 'packaging', title: '{% trans "Packaging" %}', From 01328075eac6b428fa1d8ca776c05f1a3e6f7e09 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 15 Jun 2021 23:05:03 +1000 Subject: [PATCH 284/300] All "development" related stuff now goes under ./dev - Update dev-config.env - Update docker-compose.dev.yml - Development target of Dockerfile no longer creates any folders - Update entry point scripts --- .gitignore | 5 ++++- docker/Dockerfile | 13 +++++-------- docker/dev-config.env | 14 ++++++++------ docker/docker-compose.dev.yml | 20 ++++++++++---------- docker/start_dev_server.sh | 15 ++++++++------- docker/start_dev_worker.sh | 6 +++--- 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 7c360a8231..849cc21f2a 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,7 @@ secret_key.txt # Coverage reports .coverage -htmlcov/ \ No newline at end of file +htmlcov/ + +# Development files +.dev/ \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 5c5d1dc32a..9d85b8d4b6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -101,14 +101,11 @@ CMD ["bash", "./start_prod_server.sh"] FROM base as dev -# The development image requires the source code to be mounted to /home/inventree/src/ -# So from here, we don't actually "do" anything +# The development image requires the source code to be mounted to /home/inventree/ +# So from here, we don't actually "do" anything, apart from some file management -WORKDIR ${INVENTREE_SRC_DIR} +ENV INVENTREE_DEV_DIR = "${INVENTREE_HOME}/dev" -COPY start_dev_server.sh ${INVENTREE_HOME}/start_dev_server.sh -COPY start_dev_worker.sh ${INVENTREE_HOME}/start_dev_worker.sh -RUN chmod 755 ${INVENTREE_HOME}/start_dev_server.sh -RUN chmod 755 ${INVENTREE_HOME}/start_dev_worker.sh +WORKDIR ${INVENTREE_HOME} -CMD ["bash", "/home/inventree/start_dev_server.sh"] +CMD ["bash", "/home/inventree/docker/start_dev_server.sh"] diff --git a/docker/dev-config.env b/docker/dev-config.env index 200c3db479..4d67c35da6 100644 --- a/docker/dev-config.env +++ b/docker/dev-config.env @@ -1,7 +1,9 @@ INVENTREE_DB_ENGINE=sqlite3 -INVENTREE_DB_NAME=/home/inventree/src/inventree_docker_dev.sqlite3 -INVENTREE_MEDIA_ROOT=/home/inventree/src/inventree_media -INVENTREE_STATIC_ROOT=/home/inventree/src/inventree_static -INVENTREE_CONFIG_FILE=/home/inventree/src/config.yaml -INVENTREE_SECRET_KEY_FILE=/home/inventree/src/secret_key.txt -INVENTREE_DEBUG=true \ No newline at end of file +INVENTREE_DB_NAME=/home/inventree/dev/inventree_db.sqlite3 +INVENTREE_MEDIA_ROOT=/home/inventree/dev/media +INVENTREE_STATIC_ROOT=/home/inventree/dev/static +INVENTREE_CONFIG_FILE=/home/inventree/dev/config.yaml +INVENTREE_SECRET_KEY_FILE=/home/inventree/dev/secret_key.txt +INVENTREE_DEBUG=true +INVENTREE_WEB_ADDR=127.0.0.1 +INVENTREE_WEB_PORT=8000 \ No newline at end of file diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index ddf50135c9..ee1ec101ca 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -13,8 +13,8 @@ version: "3.8" services: # InvenTree web server services # Uses gunicorn as the web server - inventree-server: - container_name: inventree-server + inventree-dev-server: + container_name: inventree-dev-server build: context: . target: dev @@ -22,7 +22,7 @@ services: - 8000:8000 volumes: # Ensure you specify the location of the 'src' directory at the end of this file - - src:/home/inventree/src + - src:/home/inventree env_file: # Environment variables required for the dev server are configured in dev-config.env - dev-config.env @@ -30,17 +30,17 @@ services: restart: unless-stopped # Background worker process handles long-running or periodic tasks - inventree-worker: - container_name: inventree-worker + inventree-dev-worker: + container_name: inventree-dev-worker build: context: . target: dev - entrypoint: /home/inventree/start_dev_worker.sh + entrypoint: /home/inventree/docker/start_dev_worker.sh depends_on: - - inventree-server + - inventree-dev-server volumes: # Ensure you specify the location of the 'src' directory at the end of this file - - src:/home/inventree/src + - src:/home/inventree env_file: # Environment variables required for the dev server are configured in dev-config.env - dev-config.env @@ -55,5 +55,5 @@ volumes: type: none o: bind # This directory specified where InvenTree source code is stored "outside" the docker containers - # Note: This directory must conatin the file *manage.py* - device: /path/to/inventree/src + # By default, this directory is one level above the "docker" directory + device: ../ diff --git a/docker/start_dev_server.sh b/docker/start_dev_server.sh index d4e33a79a5..ad12ec023a 100644 --- a/docker/start_dev_server.sh +++ b/docker/start_dev_server.sh @@ -16,21 +16,22 @@ if test -f "$INVENTREE_CONFIG_FILE"; then echo "$INVENTREE_CONFIG_FILE exists - skipping" else echo "Copying config file to $INVENTREE_CONFIG_FILE" - cp $INVENTREE_SRC_DIR/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE + cp $INVENTREE_HOME/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE fi -# Setup a virtual environment -python3 -m venv inventree-docker-dev +# Setup a virtual environment (within the "dev" directory) +python3 -m venv ./dev/env -source inventree-docker-dev/bin/activate +# Activate the virtual environment +source ./dev/env/bin/activate echo "Installing required packages..." -pip install --no-cache-dir -U -r ${INVENTREE_SRC_DIR}/requirements.txt +pip install --no-cache-dir -U -r ${INVENTREE_HOME}/requirements.txt echo "Starting InvenTree server..." # Wait for the database to be ready -cd $INVENTREE_MNG_DIR +cd ${INVENTREE_HOME}/InvenTree python manage.py wait_for_db sleep 10 @@ -45,4 +46,4 @@ python manage.py migrate --run-syncdb || exit 1 python manage.py clearsessions || exit 1 # Launch a development server -python manage.py runserver 0.0.0.0:$INVENTREE_WEB_PORT +python manage.py runserver ${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT} diff --git a/docker/start_dev_worker.sh b/docker/start_dev_worker.sh index 099f447a9c..bfadc1f49a 100644 --- a/docker/start_dev_worker.sh +++ b/docker/start_dev_worker.sh @@ -2,15 +2,15 @@ echo "Starting InvenTree worker..." -cd $INVENTREE_SRC_DIR +cd $INVENTREE_HOME # Activate virtual environment -source inventree-docker-dev/bin/activate +source ./dev/env/bin/activate sleep 5 # Wait for the database to be ready -cd $INVENTREE_MNG_DIR +cd InvenTree python manage.py wait_for_db sleep 10 From 8bfdb0bec6b060b14fc0dc5081cb78765450cd87 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 15 Jun 2021 23:19:50 +1000 Subject: [PATCH 285/300] Comment fix --- docker/docker-compose.dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index ee1ec101ca..29eccc26c6 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -47,7 +47,7 @@ services: restart: unless-stopped volumes: - # NOTE: Change /path/to/src to a directory on your local machine, where the InvenTree source code is located + # NOTE: Change "../" to a directory on your local machine, where the InvenTree source code is located # Persistent data, stored external to the container(s) src: driver: local From 632ea593fe00e58a1b6b9c9e1232d854d1e56992 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 15 Jun 2021 23:40:50 +1000 Subject: [PATCH 286/300] Fix default port association --- .gitignore | 2 +- docker/dev-config.env | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 849cc21f2a..5dd3580ef6 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,4 @@ secret_key.txt htmlcov/ # Development files -.dev/ \ No newline at end of file +dev/ \ No newline at end of file diff --git a/docker/dev-config.env b/docker/dev-config.env index 4d67c35da6..fe1f073633 100644 --- a/docker/dev-config.env +++ b/docker/dev-config.env @@ -5,5 +5,5 @@ INVENTREE_STATIC_ROOT=/home/inventree/dev/static INVENTREE_CONFIG_FILE=/home/inventree/dev/config.yaml INVENTREE_SECRET_KEY_FILE=/home/inventree/dev/secret_key.txt INVENTREE_DEBUG=true -INVENTREE_WEB_ADDR=127.0.0.1 +INVENTREE_WEB_ADDR=0.0.0.0 INVENTREE_WEB_PORT=8000 \ No newline at end of file From 0821ead024eb5579b09afd8bb3f62c43a5e54d26 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 15 Jun 2021 23:51:37 +1000 Subject: [PATCH 287/300] Only provide static redirects if in DEBUG mode --- InvenTree/InvenTree/urls.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index bce493fb23..bf0838c26c 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -161,18 +161,20 @@ urlpatterns = [ url(r'^markdownx/', include('markdownx.urls')), ] -# Static file access -urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +# Server running in "DEBUG" mode? +if settings.DEBUG: + # Static file access + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) -# Media file access -urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + # Media file access + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -# Debug toolbar access (if in DEBUG mode) -if settings.DEBUG and 'debug_toolbar' in settings.INSTALLED_APPS: - import debug_toolbar - urlpatterns = [ - path('__debug/', include(debug_toolbar.urls)), - ] + urlpatterns + # Debug toolbar access (only allowed in DEBUG mode) + if 'debug_toolbar' in settings.INSTALLED_APPS: + import debug_toolbar + urlpatterns = [ + path('__debug/', include(debug_toolbar.urls)), + ] + urlpatterns # Send any unknown URLs to the parts page urlpatterns += [url(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')] From 058fc57ff1ca2a46d09661d8e781182cb1b11f43 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 20:57:24 +1000 Subject: [PATCH 288/300] Serve media files via nginx --- docker/nginx.conf | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docker/nginx.conf b/docker/nginx.conf index 754a7321bb..fb1906f0fa 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -34,4 +34,15 @@ server { add_header Cache-Control "public"; } + # Redirect any requests for media files + location /media/ { + alias /var/www/media/; + autoindex on; + + # Caching settings + expires 30d; + add_header Pragma public; + add_header Cache-Control "public"; + } + } \ No newline at end of file From acd7322ff042123a451495338bd8a27de3ffb0c8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 21:30:25 +1000 Subject: [PATCH 289/300] Files under /media require session to be authenticated References: - https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/apache-auth/ - https://stackoverflow.com/questions/46421589/nginx-location-and-django-auth - https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-subrequest-authentication/ - https://pawamoy.github.io/posts/django-auth-server-for-shiny/ --- InvenTree/InvenTree/urls.py | 3 +++ InvenTree/InvenTree/views.py | 15 ++++++++++++++- docker/nginx.conf | 19 ++++++++++++++----- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index bf0838c26c..0108418517 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -37,6 +37,7 @@ from django.conf.urls.static import static from django.views.generic.base import RedirectView from rest_framework.documentation import include_docs_urls +from .views import auth_request from .views import IndexView, SearchView, DatabaseStatsView from .views import SettingsView, EditUserView, SetPasswordView from .views import CurrencySettingsView, CurrencyRefreshView @@ -155,6 +156,8 @@ urlpatterns = [ url(r'^search/', SearchView.as_view(), name='search'), url(r'^stats/', DatabaseStatsView.as_view(), name='stats'), + url(r'^auth/?', auth_request), + url(r'^api/', include(apipatterns)), url(r'^api-doc/', include_docs_urls(title='InvenTree API')), diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 108908c571..06aec54c18 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -10,7 +10,7 @@ from __future__ import unicode_literals from django.utils.translation import gettext_lazy as _ from django.template.loader import render_to_string -from django.http import JsonResponse, HttpResponseRedirect +from django.http import HttpResponse, JsonResponse, HttpResponseRedirect from django.urls import reverse_lazy from django.conf import settings @@ -36,6 +36,19 @@ from .helpers import str2bool from rest_framework import views +def auth_request(request): + """ + Simple 'auth' endpoint used to determine if the user is authenticated. + Useful for (for example) redirecting authentication requests through + django's permission framework. + """ + + if request.user.is_authenticated: + return HttpResponse(status=200) + else: + return HttpResponse(status=403) + + class TreeSerializer(views.APIView): """ JSON View for serializing a Tree object. diff --git a/docker/nginx.conf b/docker/nginx.conf index fb1906f0fa..270378735e 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -1,3 +1,4 @@ + server { # Listen for connection on (internal) port 80 @@ -37,12 +38,20 @@ server { # Redirect any requests for media files location /media/ { alias /var/www/media/; - autoindex on; - # Caching settings - expires 30d; - add_header Pragma public; - add_header Cache-Control "public"; + # Media files require user authentication + auth_request /auth; + } + + # Use the 'user' API endpoint for auth + location /auth { + internal; + + proxy_pass http://inventree-server:8000/auth/; + + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-URI $request_uri; } } \ No newline at end of file From 7dd63b36dacec70ce440eebe4ecb5613133b79a0 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 22:36:05 +1000 Subject: [PATCH 290/300] Simplify dockerfile / docker-compose - Single data volume now also includes 'static' files - InvenTree source repo is now cloned into /home/inventree (to match the "dev" image) --- docker/Dockerfile | 31 +++++++++++-------- docker/docker-compose.yml | 17 +++++----- docker/start_prod_server.sh | 2 +- .../{start_worker.sh => start_prod_worker.sh} | 0 4 files changed, 27 insertions(+), 23 deletions(-) rename docker/{start_worker.sh => start_prod_worker.sh} (100%) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9d85b8d4b6..e27bd5591a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -7,6 +7,8 @@ ARG branch="master" ENV PYTHONUNBUFFERED 1 # InvenTree key settings + +# The INVENTREE_HOME directory is where the InvenTree source repository will be located ENV INVENTREE_HOME="/home/inventree" # GitHub settings @@ -17,10 +19,9 @@ ENV INVENTREE_LOG_LEVEL="INFO" ENV INVENTREE_DOCKER="true" # InvenTree paths -ENV INVENTREE_SRC_DIR="${INVENTREE_HOME}/src" -ENV INVENTREE_MNG_DIR="${INVENTREE_SRC_DIR}/InvenTree" +ENV INVENTREE_MNG_DIR="${INVENTREE_HOME}/InvenTree" ENV INVENTREE_DATA_DIR="${INVENTREE_HOME}/data" -ENV INVENTREE_STATIC_ROOT="${INVENTREE_HOME}/static" +ENV INVENTREE_STATIC_ROOT="${INVENTREE_DATA_DIR}/static" ENV INVENTREE_MEDIA_ROOT="${INVENTREE_DATA_DIR}/media" ENV INVENTREE_CONFIG_FILE="${INVENTREE_DATA_DIR}/config.yaml" @@ -44,8 +45,6 @@ RUN addgroup -S inventreegroup && adduser -S inventree -G inventreegroup WORKDIR ${INVENTREE_HOME} -RUN mkdir -p ${INVENTREE_STATIC_ROOT} - # Install required system packages RUN apk add --no-cache git make bash \ gcc libgcc g++ libstdc++ \ @@ -78,23 +77,22 @@ RUN pip install --no-cache-dir -U gunicorn FROM base as production # Clone source code RUN echo "Downloading InvenTree from ${INVENTREE_REPO}" -RUN git clone --branch ${INVENTREE_BRANCH} --depth 1 ${INVENTREE_REPO} ${INVENTREE_SRC_DIR} +RUN git clone --branch ${INVENTREE_BRANCH} --depth 1 ${INVENTREE_REPO} ${INVENTREE_HOME} # Install InvenTree packages -RUN pip install --no-cache-dir -U -r ${INVENTREE_SRC_DIR}/requirements.txt +RUN pip install --no-cache-dir -U -r ${INVENTREE_HOME}/requirements.txt # Copy gunicorn config file COPY gunicorn.conf.py ${INVENTREE_HOME}/gunicorn.conf.py # Copy startup scripts -COPY start_prod_server.sh ${INVENTREE_SRC_DIR}/start_prod_server.sh -COPY start_worker.sh ${INVENTREE_SRC_DIR}/start_worker.sh +COPY start_prod_server.sh ${INVENTREE_HOME}/start_prod_server.sh +COPY start_prod_worker.sh ${INVENTREE_HOME}/start_prod_worker.sh -RUN chmod 755 ${INVENTREE_SRC_DIR}/start_prod_server.sh -RUN chmod 755 ${INVENTREE_SRC_DIR}/start_worker.sh +RUN chmod 755 ${INVENTREE_HOME}/start_prod_server.sh +RUN chmod 755 ${INVENTREE_HOME}/start_prod_worker.sh -# exec commands should be executed from the "src" directory -WORKDIR ${INVENTREE_SRC_DIR} +WORKDIR ${INVENTREE_HOME} # Let us begin CMD ["bash", "./start_prod_server.sh"] @@ -106,6 +104,13 @@ FROM base as dev ENV INVENTREE_DEV_DIR = "${INVENTREE_HOME}/dev" +# Override default path settings +ENV INVENTREE_STATIC_ROOT="${INVENTREE_DEV_DIR}/static" +ENV INVENTREE_MEDIA_ROOT="${INVENTREE_DEV_DIR}/media" +ENV INVENTREE_CONFIG_FILE="${INVENTREE_DEV_DIR}/config.yaml" +ENV INVENTREE_SECRET_KEY_FILE="${INVENTREE_DEV_DIR}/secret_key.txt" + WORKDIR ${INVENTREE_HOME} +# Launch the development server CMD ["bash", "/home/inventree/docker/start_dev_server.sh"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 9e77dd1181..0ec135c7bb 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -30,6 +30,7 @@ services: - POSTGRES_USER=pguser - POSTGRES_PASSWORD=pgpassword volumes: + # Map 'data' volume such that postgres database is stored externally - data:/var/lib/postgresql/data/ restart: unless-stopped @@ -43,8 +44,8 @@ services: depends_on: - inventree-db volumes: + # Map 'data' volume - data:/home/inventree/data - - static:/home/inventree/static environment: # Default environment variables are configured to match the 'db' container # Note: If you change the database image, these will need to be adjusted @@ -67,7 +68,6 @@ services: - inventree-server volumes: - data:/home/inventree/data - - static:/home/inventree/static environment: # Default environment variables are configured to match the 'db' container # Note: If you change the database image, these will need to be adjusted @@ -81,7 +81,8 @@ services: restart: unless-stopped # nginx acts as a reverse proxy - # static files are served by nginx + # static files are served directly by nginx + # media files are served by nginx, although authentication is redirected to inventree-server # web requests are redirected to gunicorn # NOTE: You will need to provide a working nginx.conf file! inventree-proxy: @@ -93,11 +94,11 @@ services: # Change "1337" to the port that you want InvenTree web server to be available on - 1337:80 volumes: - # Provide nginx.conf file to the container + # Provide ./nginx.conf file to the container # Refer to the provided example file as a starting point - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - # Static data volume is mounted to /var/www/static - - static:/var/www/static:ro + # nginx proxy needs access to static and media files + - data:/var/www restart: unless-stopped volumes: @@ -110,6 +111,4 @@ volumes: o: bind # This directory specified where InvenTree data are stored "outside" the docker containers # Change this path to a local system path where you want InvenTree data stored - device: /path/to/data - # Static files, shared between containers - static: \ No newline at end of file + device: /path/to/data \ No newline at end of file diff --git a/docker/start_prod_server.sh b/docker/start_prod_server.sh index 2e5acb5c9d..9d86b331eb 100644 --- a/docker/start_prod_server.sh +++ b/docker/start_prod_server.sh @@ -16,7 +16,7 @@ if test -f "$INVENTREE_CONFIG_FILE"; then echo "$INVENTREE_CONFIG_FILE exists - skipping" else echo "Copying config file to $INVENTREE_CONFIG_FILE" - cp $INVENTREE_SRC_DIR/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE + cp $INVENTREE_HOME/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE fi echo "Starting InvenTree server..." diff --git a/docker/start_worker.sh b/docker/start_prod_worker.sh similarity index 100% rename from docker/start_worker.sh rename to docker/start_prod_worker.sh From d85b906560d31f1fd8d85ea6c5a9f0d6e3f1c7dd Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 22:57:31 +1000 Subject: [PATCH 291/300] Fix comment in docker-compose.yml file --- docker/docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0ec135c7bb..8c2a0b4e23 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -44,7 +44,7 @@ services: depends_on: - inventree-db volumes: - # Map 'data' volume + # Data volume must map to /home/inventree/data - data:/home/inventree/data environment: # Default environment variables are configured to match the 'db' container @@ -67,6 +67,7 @@ services: - inventree-db - inventree-server volumes: + # Data volume must map to /home/inventree/data - data:/home/inventree/data environment: # Default environment variables are configured to match the 'db' container From 725d26d76fab0a938b8df8917490548ef6950c61 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 23:03:09 +1000 Subject: [PATCH 292/300] Fix default paths in InvenTree settings --- InvenTree/InvenTree/settings.py | 2 +- InvenTree/config_template.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 618c9f730f..208472ff2e 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -191,7 +191,7 @@ STATIC_URL = '/static/' STATIC_ROOT = os.path.abspath( get_setting( 'INVENTREE_STATIC_ROOT', - CONFIG.get('static_root', '/home/inventree/static') + CONFIG.get('static_root', '/home/inventree/data/static') ) ) diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 1333b876b8..1f73181cf5 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -131,7 +131,7 @@ media_root: '/home/inventree/data/media' # STATIC_ROOT is the local filesystem location for storing static files # By default, it is stored under /home/inventree # Use environment variable INVENTREE_STATIC_ROOT -static_root: '/home/inventree/static' +static_root: '/home/inventree/data/static' # Optional URL schemes to allow in URL fields # By default, only the following schemes are allowed: ['http', 'https', 'ftp', 'ftps'] From 513449e13ca0be54578b389ee20f396a4c0f3b3c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 23:03:38 +1000 Subject: [PATCH 293/300] Whoops, missed one --- InvenTree/config_template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 1f73181cf5..0e6232d270 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -129,7 +129,7 @@ cors: media_root: '/home/inventree/data/media' # STATIC_ROOT is the local filesystem location for storing static files -# By default, it is stored under /home/inventree +# By default, it is stored under /home/inventree/data/static # Use environment variable INVENTREE_STATIC_ROOT static_root: '/home/inventree/data/static' From 8e9bf2aadd1d44831f7c42292c461530205c0b8d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 16 Jun 2021 23:31:36 +1000 Subject: [PATCH 294/300] Fix typo in docker-compose.yml --- docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 8c2a0b4e23..dcd35af148 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -62,7 +62,7 @@ services: inventree-worker: container_name: inventree-worker image: inventree/inventree:latest - entrypoint: ./start_worker.sh + entrypoint: ./start_prod_worker.sh depends_on: - inventree-db - inventree-server From 731ea0238e5c73e899ee21b03206ea7fe088c5a1 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 16 Jun 2021 23:53:58 +1000 Subject: [PATCH 295/300] Update version.py Bump version number --- InvenTree/InvenTree/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 7b8546b1c2..305828c869 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -8,7 +8,7 @@ import re import common.models -INVENTREE_SW_VERSION = "0.2.3 pre" +INVENTREE_SW_VERSION = "0.2.3" """ Increment thi API version number whenever there is a significant change to the API that any clients need to know about From 9386332de1770496a23ccddaa448f87794121e39 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 16 Jun 2021 23:54:42 +1000 Subject: [PATCH 296/300] Update version.py --- InvenTree/InvenTree/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 305828c869..5161bee6a1 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -8,7 +8,7 @@ import re import common.models -INVENTREE_SW_VERSION = "0.2.3" +INVENTREE_SW_VERSION = "0.2.4 pre" """ Increment thi API version number whenever there is a significant change to the API that any clients need to know about From 70e093333627d5340003d0ea816c7fa368af0b47 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 16 Jun 2021 23:52:00 +0200 Subject: [PATCH 297/300] total price column as per #1660 --- .../templates/order/purchase_order_detail.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index ef844409fd..fda45240dc 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -182,6 +182,20 @@ $("#po-table").inventreeTable({ return row.purchase_price_string || row.purchase_price; } }, + { + sortable: true, + title: '{% trans "Total price" %}', + formatter: function(value, row) { + var total = row.purchase_price * row.quantity; + + // Create our number formatter. + var formatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: row.purchase_price_currency, + }); + return formatter.format(total) + }, + }, { sortable: true, field: 'received', From 2fc185bd7147abf1beff6924adb1c98008b830d1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 16 Jun 2021 23:57:33 +0200 Subject: [PATCH 298/300] show footer --- InvenTree/order/templates/order/purchase_order_detail.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index fda45240dc..155fb50eae 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -117,6 +117,7 @@ $("#po-table").inventreeTable({ part_detail: true, }, url: "{% url 'api-po-line-list' %}", + showFooter: true, columns: [ { field: 'pk', @@ -137,6 +138,9 @@ $("#po-table").inventreeTable({ return '-'; } }, + footerFormatter: function() { + return 'Total' + } }, { field: 'part_detail.description', From dac112d9081a0aacb69a61fa5fdbc6b33336d8ed Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 17 Jun 2021 00:22:32 +0200 Subject: [PATCH 299/300] added footer total for price --- .../templates/order/purchase_order_detail.html | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index 155fb50eae..acfce032e7 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -191,14 +191,20 @@ $("#po-table").inventreeTable({ title: '{% trans "Total price" %}', formatter: function(value, row) { var total = row.purchase_price * row.quantity; - - // Create our number formatter. - var formatter = new Intl.NumberFormat('en-US', { - style: 'currency', - currency: row.purchase_price_currency, - }); + var formatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: row.purchase_price_currency}); return formatter.format(total) }, + footerFormatter: function(data) { + var total = data.map(function (row) { + return +row['purchase_price']*row['quantity'] + }).reduce(function (sum, i) { + return sum + i + }, 0) + var currency = (data.slice(-1)[0] && data.slice(-1)[0].purchase_price_currency) || 'USD'; + var formatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: currency}); + return formatter.format(total) + } + }, { sortable: true, From 5d3360e63b2666f6dd8a4268b60354bef43ee6fa Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 17 Jun 2021 00:23:08 +0200 Subject: [PATCH 300/300] added quantity total --- .../order/templates/order/purchase_order_detail.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html index acfce032e7..08236fe773 100644 --- a/InvenTree/order/templates/order/purchase_order_detail.html +++ b/InvenTree/order/templates/order/purchase_order_detail.html @@ -176,7 +176,14 @@ $("#po-table").inventreeTable({ { sortable: true, field: 'quantity', - title: '{% trans "Quantity" %}' + title: '{% trans "Quantity" %}', + footerFormatter: function(data) { + return data.map(function (row) { + return +row['quantity'] + }).reduce(function (sum, i) { + return sum + i + }, 0) + } }, { sortable: true, @@ -204,7 +211,6 @@ $("#po-table").inventreeTable({ var formatter = new Intl.NumberFormat('en-US', {style: 'currency', currency: currency}); return formatter.format(total) } - }, { sortable: true,